Hi there,
I am newer at ARM programming but I need to get I2C communication working to read from accelerometer. For beggining I would like to get at least some bits transfered on I2C pins. In this forum I have found I2C example: http://www.keil.com/forum/58249/
I have included it to me project so now it should send some data on timmer interrupt. But at I2C pins connected scope only shows 1 pulse down to 0V at timmer interrupts.
Any help would be appreciate.
Please find me source code bellow:
#include "LPC11xx.h" /* LPC11xx definitions */ #include "gpio.h" #include <cr_section_macros.h> #include <NXP/crp.h>
// Variable to store CRP value in. Will be placed automatically // by the linker when "Enable Code Read Protect" selected. // See crp.h header for more information __CRP const unsigned int CRP_WORD = CRP_NO_CRP ;
int i=0; unsigned int status = 0;
void timer16_0_setup(void) { //Set up 16 bit timer LPC_SYSCON->SYSAHBCLKCTRL |= (1<<7); //enable timer clock LPC_TMR16B0->PR = 48000-1; //prescaler 48000 = 1ms LPC_TMR16B0->MCR = (3<<3); //interrupt and reset counter match1 LPC_TMR16B0->CCR = 0; //timer mode LPC_TMR16B0->MR1 = 1000-1; //set match1 time in us NVIC_EnableIRQ(TIMER_16_0_IRQn); //enable interrupt LPC_TMR16B0->TCR = 1; //start timer }
void I2C_Init(void) { LPC_SYSCON->PRESETCTRL |= (1<<1); //De-Asserts Reset Signal to I2C LPC_SYSCON->SYSAHBCLKCTRL |= (1<<5); //Enable I2C Clock
LPC_IOCON->PIO0_4 &= ~0x3F; LPC_IOCON->PIO0_4 |= 0x01; //SCL
LPC_IOCON->PIO0_5 &= ~0x3F; LPC_IOCON->PIO0_5 |= 0x01; //SDA
//I2C 100 LPC_I2C->SCLH = 360; //I2PCLK is 72MHz LPC_I2C->SCLL = 360; //I2PCLK is 72MHz
LPC_I2C->CONCLR = 0xFF; //Clear All Flags LPC_I2C->CONSET = (1<<6); //I2C Interface Enable } void I2C_Start(void) { LPC_I2C->CONCLR = 0X28; LPC_I2C->CONSET |= 0x20; //Set the Start Bit while(LPC_I2C->STAT!=0x08); //Wait for the Status Bit } void I2C_Restart(void) { LPC_I2C->CONCLR = 0X28; LPC_I2C->CONSET |= 0x20; //Set the Start Bit while(LPC_I2C->STAT!=0x10); //Wait for the Status Bit } void I2C_Stop(void) { LPC_I2C->CONSET |= 0x14; //Stop I2C LPC_I2C->CONCLR = 0x08; } void I2C_Write(unsigned char data,unsigned char status) { LPC_I2C->CONCLR = 0X28; LPC_I2C->DAT = data; LPC_I2C->CONCLR = 0X28; //Clear Start Flag and SI Interrupt //while(LPC_I2C->STAT!=status); //Wait for the Status Byte } unsigned char I2C_Read(void) { LPC_I2C->CONCLR = 0X2C; //Cleat SI and Asset Acknowledgment Flag while(LPC_I2C->STAT!=0x58); return(LPC_I2C->DAT); }
//Timer interrupt void TIMER16_0_IRQHandler(void) { if(LPC_TMR16B0->IR & (1<<1)) //match1 interrupt? { if (i==0) {GPIOSetValue( 1, 7, 1 ); i=1;} else {GPIOSetValue( 1, 7, 0 ); i=0;}
I2C_Start(); I2C_Write(100,1); I2C_Stop();
} LPC_TMR16B0->IR = (1<<1); //reset flag
} //end match1 interrupt
int main (void) {
//Set up timer timer16_0_setup(); I2C_Init(); GPIOInit();
// Set port for LED to output GPIOSetDir( 1, 7, 1 );
while (1) // Loop forever {
} }
It's not possible to learn from just source code when the learning relates to embedded hardware - you need to keep one eye on the source code and the other eye on the hardware documentation.
It's trivial to see the source code assign a value to a register - but you can't know exactly what that line does or why it does it unless you also look at the specification for the register. And most of the time, it isn't enough to read the documentation for the register. You need to read the full chapter for that peripheral hardware to see how the register interacts with other parts of the device functionality.
Same thing if you want to learn Windows programming and decides to read source code - you would also need to read the API documentation to pick up the actual meaning of the individual function calls. And what alternative options you would get if you change the set of flags or parameter values you send to the API.
Lots of people have learned the mechanics or cars without reading specifications. You can get far with just dismantling gear and then put it together again. It works great if you just want to repair the car to the original specifications. But if you want to redesign it, you either need to spend time reading engineering texts or take a part a rather large number of different cars just to learn all the different ways things can interact.
Programming isn't about repairing a program to the original specification. It's about designing new functionality. That's why it doesn't work well to just try to cut and paste code - it's important to know what the different pieces actually does, to know how they can be adapted to fit together when reusing them in a new program.
So while it's possible to learn lots of new tricks by reading other peoples code, you'll need to complement the code reading with time spent with reference documentation.
-> void I2C_Write(unsigned char data,unsigned char status). I don't know what argument "status" should be.
-> while(LPC_I2C->STAT!=status); //Wait for the Status Byte
-> Any ideas what status I need to wait for?
The source code you choose to use, did not come with a testable main(). The source code I provided, came with a testable main(). Would you mind giving my source code a try?
Thanks a lot John,
I have checked your source code with my LPC1115 evaluation board and that works perfect! Having working code I at least know what to check in datasheet. Your post was very helpful.