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 {
} }
If you had spent some time looking at the information presented to you before you posted, you could have ended up with code looking like:
#include <stdio.h> int main(void) { printf("Hello World!\n"); return 0; }
There is a reason why the posting instructions has a sentence starting with "Place source code between [...]".
Oh dear.
You can lead a horse to water but it's pretty damn crowded there because of all the men you tried to teach to fish with that other proverb.
Ok, no problem, but does anyone have answer to me topic instead of writing stupid jokes
-> In this forum I have found I2C example: -> http://www.keil.com/forum/58249/ The mentioned thread and the source code there, is for LPC1343, not for LPC1111. And you can't just copy some code from one project to another, without any understanding, expecting it would work for you.
Try to find some example designed for LPC1111. Study it before use it.
Thanks, jap I have checked. For me all registers used in this source code look the same. I suppose I2C is one of the simples communication way so it shouldn't be so hard, but I am strugling with it.
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
Can you confirm that for LPC1111, the PIO0_4, PIO0_5 are for I2C SCL, SDA?
Yes they are. I am using HVQFN 33 package of LPC1111. I am getting now pulse down on SCL and SDA pins every timer match interrupt. I have spoted one thing in me code that can be wrong:
I guess I need to exchange lines to this
I2C_Write(100,1); I2C_Start(); I2C_Stop();
I will check this later.
I have exchange lines and tested. LPC hangs in write function.
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?
Thanks
And that's the core of your actual problem: instead of learning how I2C in general, or the I2C implementation on this micro actually works, you just start throwing wild guesses around. That's no way to develop low-level software.
And after roughly a half dozen hints, you still can't be bothered to format your source code properly. Combined these two indicate that you either cannot, or don't want to be helped.
Actually, I2C is rather more complicated than some - with all the Start Conditions, Stop Conditions, Addressing, ACKs, etc.
"I am strugling with it"
As already noted, you really do need to take some time to understand what's going on with both I2C in general and the I2C hardware within your particular microcontroller & peripheral.
The full I2C specification is here:
www.nxp.com/.../UM10204.pdf
The datasheet and/or User Manual for the microcontroller will explain how its I2C hardware works. Also check the manufacturer's website for examples, application notes, etc. In this case, NXP: www.nxp.com/.../8kb-flash-4kb-sram-hvqfn32-package:LPC1111FHN33
If you're using a library, you will need to study its documentation to find out how to use it effectively.
In this case (NXP), see also: http://www.lpcware.com/
or https://www.lpcware.com/
Thanks,
To learn from source examples is much easier for me, but looks like i will do try to study I2C basics.
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.