Hallo Zusammen
Ich muss eine kommunikation über I2C machen, dabei bekomme ich kommandos
von einem mainboard (ich als Slave) und muss das dann andere Slaves
ansteuern.
Das klappt soweit eigentlich, nur gibts da ein paar Probleme.
1. wenn ich breakpoints setze funktioniert das senden an die slaves
nicht mehr. Sobald ich die wegnehme läuft das testprogramm durch und
alles wird gesendet.
2. ich kann zwar daten empfangen wenn ich im MultiMasterMode bin (UCMM),
jedoch muss ich in der senden Funktion wieder alle Register auf master
umschalten damit irgendwas gesendet wird.
3. muss ich nach jedem senden eine verzögerung einbauen, damit das Byte
auch sicher ankommt. ich habe diese verzögerung einfach mit einer
sinnlosen schleife gemacht welche 5 mal durchläuft. da dies jedoch
unsauber ist, habe ich es durch ein while ersetzt ähnlich wie in den TI
codesamples, nur das scheint auch nicht so richtig zu funktionieren.
1 | // Multi Master:
|
2 | void main(void){
|
3 | WDTCTL = WDTPW + WDTHOLD; // Stop wdt
|
4 |
|
5 | P3SEL |= 0x06; // Assign I2C pins to USCI_B0
|
6 | UCB0CTL1 |= UCSWRST; // Enable SW reset
|
7 | UCB0CTL0 = UCMM + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode
|
8 | UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset
|
9 | UCB0BR0 = 12; // fSCL = SMCLK/12 = ~100kHz
|
10 | UCB0BR1 = 0;
|
11 | UCB0I2COA = 0x48; // Own Address is 048h
|
12 | UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
|
13 | IE2 |= UCB0RXIE | UCB0TXIE; // Enable RX & TX interrupt
|
14 |
|
15 | while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
|
16 | UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition
|
17 | __bis_SR_register(CPUOFF + GIE); // Enter LPM0 w/ interrupts
|
18 |
|
19 | while(RXData != 0x12);
|
das programm wartet bis der uP 0x12 empfängt, das klappt wunderbar.
danach wird einem slave ein kommando geschickt (0x01) und dann dieser
slave wieder ausgelesen. das funktioniert nur wenn vorher keine
breakpoints gemacht werden.
1 | unsigned char ret = 0;
|
2 | ret++; // Wenn hier Breakpoint, dann klappts ned
|
3 | sendByte(0x01, 0xB);
|
4 | ret = readByte(0xB);
|
5 | ret++; // Wenn hier Breakpoint dann klappts
|
6 | return;
|
7 | }
|
die send funktion:
1 | void sendByte(char Byte, char slaveAdr){
|
2 | P3SEL |= 0x06; // Assign I2C pins to USCI_B0
|
3 | UCB0CTL1 |= UCSWRST; // Enable SW reset
|
4 | UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode
|
5 | UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset
|
6 | UCB0BR0 = 12; // fSCL = SMCLK/12 = ~100kHz
|
7 | UCB0BR1 = 0;
|
8 | UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
|
9 | IE2 |= UCB0TXIE; // Enable TX interrupt
|
10 |
|
11 | // alles oberhalb von hier sollte ja eigentlich nicht nötig sein, aber es geht sonst nicht
|
12 |
|
13 | UCB0I2CSA = slaveAdr; // set Slave Address
|
14 |
|
15 | g_TXData = Byte;
|
16 | g_TXByteCtr = 0x01;
|
17 | while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
|
18 | UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition
|
19 | __bis_SR_register(CPUOFF + GIE); // Enter LPM0 w/ interrupts
|
20 | // Remain in LPM0 until all data is TX'd
|
21 | while (UCB0CTL1 & UCTXSTP);
|
22 | return;
|
23 | }
|
am schluss dieser funktion bleibt der uP hängen, wenn ich breakpoints
gesetzt habe [ while (UCB0CTL1 & UCTXSTP); ]. dieses while habe ich
gemacht um die stop condition zu checken (wie weiter oben). nur ich habe
keine ahnung ob das so stimmt, ohne wird einfach nichts gesendet, ausser
ich mache eine kleine schlaufe mit ca 5 NOPs oder so, also einfach eine
kleine verzögerung.
die empfangen funktion ist ähnlich, auch da muss ich wieder alle
register umstellen.
die interrupt routine:
1 | #pragma vector = USCIAB0TX_VECTOR
|
2 | __interrupt void USCIAB0TX_ISR(void){
|
3 | if(UC0IFG & UCB0TXIFG){ // check send or recieve
|
4 | if(g_TXByteCtr){
|
5 | UCB0TXBUF = g_TXData; // Load TX buffer
|
6 | g_TXByteCtr--;
|
7 | }else{
|
8 | UCB0CTL1 |= UCTXSTP; // I2C stop condition
|
9 | IFG2 &= ~UCB0TXIFG; // Clear USCI_B0 TX int flag
|
10 | __bic_SR_register_on_exit(CPUOFF); // Exit LPM0
|
11 | }
|
12 | }else{
|
13 | RXData = UCB0RXBUF; // Get RX data
|
14 | __bic_SR_register_on_exit(CPUOFF); // Exit LPM0
|
15 | }
|
16 | }
|
hier kann ich zwar unterscheiden zwischen senden und empfangen, jedoch
weiss ich nicht ob ich aktiv was lese (vom slave) oder ob ich was von
einem anderen master empfange. muss ich da selber mit globalen variabeln
das checken, oder gibts da ne elegantere lösung?
ich hoffe das war verständlich :D
danke für jede hilfe
lars