|
|
View previous topic :: View next topic |
Author |
Message |
small_chick
Joined: 17 Jul 2012 Posts: 53
|
error appears when trying to add a c file of a module ??? |
Posted: Wed Aug 01, 2012 3:25 am |
|
|
I'm trying to separate my main c file into 2 file: MMA8452.c and main.c.
In main.c, i call some functions in MMA8452.c, but there is error that i will show you below.
This my code for MMA8452.c:
Code: |
//----------------------------------------------
#ifndef MMA8452_C
#define MMA8452_C
//----------------------------------------------
//define register addresses of MMA8452.
#define CTRL_REG1 0x2A
#define PL_CFG 0x11
#define PL_BF_ZCOMP 0x13
#define CTRL_REG4 0x2D
#define CTRL_REG5 0x2E
#define CTRL_REG2 0x2B
#define PL_COUNT 0x12
#define CTRL_REG3 0x2C
#define STATUS 0x00
#define INT_SOURCE 0x0C
#define PL_STATUS 0x10
#define OUT_X_MSB 0x01
//********************************************
byte i2c_register_read( byte register_address)
{
byte register_value;
i2c_start();
i2c_write(0x38);//write [(Device Address)+(write command)].Note: the SA0 input = 0 !!!
i2c_write(register_address); //write [register address].
i2c_start();//re-start.
i2c_write(0x39);//write [(Device Address)+(read command)].Note: the SA0 input = 0 !!!
register_value = i2c_read(0);//send slave read command and "N-ACK" attachment.
i2c_stop();
return register_value;
}
//---------------------------------------------
void i2c_register_write(byte register_address,byte assigned_value)
{
i2c_start();
i2c_write(0x38);//write [(Device Address)+(write command)].Note: the SA0 input = 0 !!!
i2c_write(register_address); //write [register address] .
i2c_write(assigned_value);//write [assigned value] into the register determined above.
i2c_stop();
}
//---------------------------------------------
void Standby_Mode()
{
byte n;
/*
** Read current value of System Control 1 Register.
** Put sensor into Standby Mode by clearing the Active bit.
** Return new value to System Control 1 Register.
*/
n = i2c_register_read(CTRL_REG1);
i2c_register_write(CTRL_REG1,n & 0xFE);
}
//--------------------------------------------
void Active_Mode()
{
byte n;
/*
** Read current value of System Control 1 Register.
** Put sensor into Active Mode by setting the Active bit.
** Return new value to System Control 1 Register.
*/
n = i2c_register_read(CTRL_REG1);
i2c_register_write(CTRL_REG1,n | 0x01);
}
//---------------------------------------------
void Set_Data_Rate(byte Data_Rate_value) //related to the register CTRL_REG1.
{
byte n;
//Put sendor into Standby Mode.
Standby_Mode();
//Write the desired Data Rate value into CTRL_REG1.
n = i2c_register_read(CTRL_REG1);
i2c_register_write(CTRL_REG1,n & 0xC7);//0xC7 = 0b11000111 => clear DR2:DR0 .
i2c_register_write(CTRL_REG1,n |Data_Rate_value);
//Put sendor into Active Mode.
Active_Mode();
}
//---------------------------------------------\
void Enable_PortraitLandscape_detection() //to do this, we set the PL_EN bit in Register PL_CFG.
{
byte n;
//Put sendor into Standby Mode.
Standby_Mode();
//Set the PL_EN bit in Register PL_CFG.
n = i2c_register_read(PL_CFG);
i2c_register_write(PL_CFG,n | 0x40);
//Put sendor into Active Mode.
Active_Mode();
}
//---------------------------------------------
void Set_BackFront_Angle_trip_points(byte desired_trip_points) //related to register PL_BF_ZCOMP.
{
/*
**Choices for [desired_trip_points]:
** 0x00: bits[DBCNTM:PL_EN] = 00.
** 0x40: bits[DBCNTM:PL_EN] = 01.
** 0x80: bits[DBCNTM:PL_EN] = 10.
** 0xC0: bits[DBCNTM:PL_EN] = 11.
*/
byte n;
//Put sendor into Standby Mode.
Standby_Mode();
//Choose the Back/Front Angle trip points.
n = i2c_register_read(PL_BF_ZCOMP);
n &=0x3F; //clear bit DBCNTM and PL_EN.
i2c_register_write(PL_BF_ZCOMP,n | desired_trip_points);
//Put sendor into Active Mode.
Active_Mode();
}
//---------------------------------------------
void Enable_PortraitLandscape_Interrupt()//related to the register CTRL_REG4.
{
byte n;
//Put sendor into Standby Mode.
Standby_Mode();
//Enable Portrait/Landscape Interrupt.
n = i2c_register_read(CTRL_REG4);
i2c_register_write(CTRL_REG4,n | 0x10);// set bit INT_EN_LNDPRT.
//Put sendor into Active Mode.
Active_Mode();
}
//---------------------------------------------
void Choose_interrupt_pin(byte desired_choice) //related to the register CTRL_REG5.
{
/* Option as follow:
** desired_choice = 0xEF => choose INT1 pin.
** desired_choice = 0x10 =>choose INT2 pin.
*/
byte n;
//Put sendor into Standby Mode.
Standby_Mode();
//Determine which pin is chosen.
n = i2c_register_read(CTRL_REG5);
if(desired_choice == 0xEF)
n &=0xEF;
else if(desired_choice == 0x10)
n |=0x10;
i2c_register_write(CTRL_REG5,n);
//Put sendor into Active Mode.
Active_Mode();
}
//---------------------------------------------
void Set_Oversampling_Mode(byte desired_mode)//related to the register CTRL_REG2.
{
/* 4 options as follow:
** desired_mode = 0x00: Nomral mode.
** desired_mode = 0x01: Low Noise Low Power mode.
** desired_mode = 0x02: High Resolution mode.
** desired_mode = 0x03: Low Power mode.
*/
byte n;
//Put sendor into Standby Mode.
Standby_Mode();
//Determine which mode is chosen.
n = i2c_register_read(CTRL_REG2);
n &=0xF8;// clear bits MODS[1:0].
i2c_register_write(CTRL_REG2,n|desired_mode);
//Put sendor into Active Mode.
Active_Mode();
}
//---------------------------------------------
void Set_the_debounce_counter(byte debounce_value) //related to the register PL_COUNT.
{
/* debounce_value has range of [0, 255] or [0x00, 0xFF]*/
//Put sendor into Standby Mode.
Standby_Mode();
//Assign the debounce value.
i2c_register_write(PL_COUNT,debounce_value);
//Put sendor into Active Mode.
Active_Mode();
}
//---------------------------------------------
void Set_signal_transition_on_INTx_pin(byte designed_transition)//related to the register CTRL_REG3.
{
byte n;
//Put sendor into Standby Mode.
Standby_Mode();
//configure sinal transition on INTx pin.
n = i2c_register_read(CTRL_REG3);
n &=0xFC; //clear bits IPOL and PP_OD.
i2c_register_write(CTRL_REG3,designed_transition);
//Put sendor into Active Mode.
Active_Mode();
}
//---------------------------------------------
void MMA8452_init()
{
//Note: the SA0 input = 0 !!!
//Set the data rate to 50 Hz.
Set_Data_Rate(0x00);//Data_Rate_value = 0b00100000 = 0x20 => means DR2:DR0 = 100.
//Ser Oversampling mode = Normal.
Set_Oversampling_Mode(0x00);
//Enable Portrait/Landscape detection.
Enable_PortraitLandscape_detection();
//Enable Portrait/Landscape Interrupt.
Enable_PortraitLandscape_Interrupt();
//Routing the interrupt to INT1 pin.
Choose_interrupt_pin(0xEF);
//Set the debounce counter in the register PL_COUNT.
Set_the_debounce_counter(50);/* 0x05 <=> 5 step,each step time = 20 ms ( we're in Normal mode).Therfore the
debouce time = 100ms.*/
//Set interrpt signal transition on INT1 pin is high->low when interrupt is triggered.Note: use pull-up resistor on INT1 pin.
Set_signal_transition_on_INTx_pin(0x00);
}
//-----------------------------------------
#endif
//----------------------------------------- |
Code: |
//***********************************************************//and this for main.c:
//---------------------------------------------------------
#include "16F887.h"
#use delay(clock = 4000000)
#use i2c(master,sda = PIN_C4, scl = PIN_C3)
#use RS232(parity = N,bits=8,stop=1,UART1)
#include "MMA8452.c"
//*****************************************************************************
//*****************************************************************************
#byte PORT_B = 0x06
//-------------------------------
void uart_init()
{
setup_uart(9600);
}
//*****************************************************************************
//*****************************************************************************
void main()
{
//Declaring variables.
byte register_data,LAPO_MASK ;
int1 LO_MASK,BAFRO_MASK;
unsigned char i,c,s[2];
//Initialize MMA8452 device.
MMA8452_init();
//UART starts up.
uart_init();
// putc('c');
// puts("123 \n 456 \n");
output_b(0x00);
while(1)
{
register_data = i2c_register_read(PL_STATUS);
PORT_B = ~register_data;
delay_ms(1000);
}
}
//****************************************** |
and this is the error statement:
< *** Error 128 "MMA8452.c" Line 22(1,6): A #DEVICE required before this line
>
I hope someone can help me ! thanks !
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Wed Aug 01, 2012 4:13 am |
|
|
Are you using MPLAB?.
Key thing when splitting code up like this, is that it is only the 'main' code that should be loaded directly to the compiler. This includes things like the processor definition (#device). As this is loaded, the compiler then 'includes' other files it is told to.
In MPLAB, you must only have the 'main.c' in the 'source files' file list to compile.
Then the other file is put into the 'header files' section.
If the other file (MMA8452 for you), is instead put in the 'source files' part, then the program will try to compile this _on it's own_, which will not work, since it does not contain vital stuff like the processor definitions....
Best Wishes |
|
|
small_chick
Joined: 17 Jul 2012 Posts: 53
|
|
Posted: Wed Aug 01, 2012 11:20 am |
|
|
yes, I'm using MPLAB !
as you said, i have to create an header file and then add into "header files" section of MPLAB ? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Wed Aug 01, 2012 2:14 pm |
|
|
Not quite. Your MMA8452.c, _is_ a header file.
Anything that is not a 'main' file, is a header file, whatever you call it.
Best Wishes |
|
|
small_chick
Joined: 17 Jul 2012 Posts: 53
|
|
Posted: Wed Aug 01, 2012 6:33 pm |
|
|
Would you mind telling me more clearly how I can solve this problem, Ttelmah ? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Aug 01, 2012 6:54 pm |
|
|
The Project Window in MPLAB should look like this:
Code: |
MyProject.mcp
- Source Files
- main.c
-Header Files
- 16F887.h
-Other Files
- MMA8452.c
|
It's optional to add the 16F887.h in the Header Files section, and it's
optional to add MMA8452.c to the Other Files section. The only file
that must be listed is main.c and it must be in the Source Files
section. Don't put any other files in the Source Files section.
I don't know what your project name is, so I just gave it a name of
MyProject. It will actually show your real project name.
Also, MMA8452.c must be #include'd in your main.c, but you already have
that done as shown in your posted code. |
|
|
small_chick
Joined: 17 Jul 2012 Posts: 53
|
|
Posted: Wed Aug 01, 2012 8:33 pm |
|
|
PCM programmer, it's well done ! great ! thank you very much !!! |
|
|
small_chick
Joined: 17 Jul 2012 Posts: 53
|
|
Posted: Wed Aug 01, 2012 8:39 pm |
|
|
PCM programmer, I'd like to ask you one more question !
Have you ever used Hi-Tech C compiler ?
I've seen some of my friends using it, they can add an .c file into source files and a corresponding .h file ( i means they have the same name , for example: lcd.c ans lcd.h ) in header files ! Is it a difference between Hitech-C compiler and CCS compiler ?
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Thu Aug 02, 2012 1:47 am |
|
|
Not really, but also yes....
The 'point' is that whatever is in the 'source files' section, is handed to the compiler to compile. Now you can write two separate .c files, put them in here, and have one linking in code from the other in CCS, but each would have to contain the processor definitions, and one export functions, and the other import them. So you can setup CCS to work this way, but you would then have to add the processor definitions to your second .C file, and export the functions in this, importing them in the other file.
The 'default' behaviour for CCS, is to treat the primary file handed to it, as the main code, and then link in the other files (you don't even have to mention them anywhere in MPLAB at all). Historically CCS was a compiler, without a linker. It does now have a linker, but _defaults_ to running as if it doesn't.
However key thing is that CCS will _not_ compile almost any file, without processor definitions. This is 'down' to slight differences in the nature of the functions. CCS includes a huge number of pre-written 'library' functions, that do a vast amount 'behind the scenes' for you. So (for instance), you can just call an serial output routine, and provided the header is present, the compiler does everything. HiTech, does not work this way. Instead you have to do all the settings of things like baud rate multipliers yourself. Hence you can call a generic serial routine, and this doesn't have to 'know' anything about the processor - other than it is a PIC18 for example. Because of this, HiTech can compile a lot of subroutine stuff 'generically', without needing any definition data. CCS can't.
Best Wishes |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|