Hi,
ich möchte mit einem STM32F103RB Derivat ein I2C Device ansprechen. Der
Mikrocontroller soll dabei als Master und das anzusprechende Device als
Slave fungieren. Mein Code sieht folgendermaßen aus:
Initialisierung:
1 | void init_i2c(void){
|
2 | RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; //I2C1 Clock anknipsen
|
3 |
|
4 | I2C1->CR1 &= I2C_CR1_PE; //I2C1 deaktivieren
|
5 |
|
6 | I2C1->CR1 &= I2C_CR1_SMBUS; //SMBus Mode = I2C
|
7 | I2C1->CR2 &= I2C_CR2_DMAEN; //DMA deaktivieren
|
8 | I2C1->CR2 &= I2C_CR2_ITBUFEN; //kein Interrupt bei TxE = 1 oder RXNE = 1
|
9 | I2C1->CR2 &= I2C_CR2_ITEVTEN; //Event Interrupt deaktivieren
|
10 | I2C1->CR2 &= I2C_CR2_ITERREN; //Error Interrupt deaktivieren
|
11 | I2C1->CR2 = ((I2C1->CR2 & ~I2C_CR2_FREQ) | (I2C_CR2_FREQ_3 )); //setze FREQ auf 08h
|
12 | I2C1->CCR &= I2C_CCR_FS; //Standard Mode I2C
|
13 | I2C1->CCR = 0x28; //I2C Frequenz = 100kHz
|
14 | I2C1->TRISE = 0x65; //Berechnung: siehe Datasheet
|
15 | I2C1->CR1 |= I2C_CR1_PE; //I2C1 aktivieren
|
16 |
|
17 | RCC->APB2ENR |= RCC_APB2ENR_IOPBEN; //GPIOB clock anknipsen
|
18 | RCC->APB2ENR |= RCC_APB2ENR_AFIOEN; //AFIO Clock anknipsen
|
19 | GPIOB->CRL = (GPIOB->CRL & ~0xFF000000) | 0xFF000000; //PB6 und PB7 als Alternate Function Output Open Drain
|
20 |
|
21 | }
|
Sende-Routine:
1 | void send(){
|
2 | I2C1->CR1 |= I2C_CR1_START; //sende Start-bit
|
3 | while(!(I2C1->CR1 & I2C_SR1_SB)); //warte bis SB Flag gesetzt wurde
|
4 | I2C1->DR = 0x20;//schreibe Slave Adresse ins data register (Adresse fuers Schreiben = 32dez)
|
5 | while(!(I2C1->SR1 & I2C_SR1_ADDR)); //warte bis ADDR gesetzt wurde <- hier bleibt das Programm haengen
|
6 | }
|
Und das Hauptprogramm:
1 | int main(void){
|
2 | init_i2c();
|
3 | send();
|
4 |
|
5 | for(;;){
|
6 | }
|
7 | }
|
Mir ist bewusst, dass die Sende-Routine nicht vollständig ist, doch um
das Problem einzukreisen hab ich das Programm auf das notwendigste
reduziert. Und zwar bleibt das Programm in dieser Zeile:
"while(!(I2C1->SR1 & I2C_SR1_ADDR));" hängen. Ich hab mir dann mit dem
Debugger die entsprechenden I2C1-Register angesehen und festgestellt,
dass das BUSY Flag dauerhaft gesetzt ist. Wenn ich mit dem Oszi die
Taktleitung ansehe, dann ist diese dauerhaft auf High. Da sollte ja
eigentlich ein schöner Clock zu messen sein, oder?!
Hat jemand einen Tipp was das Problem sein könnte?
Bevor ichs vergesse: Sowohl SDA als auch SCL besitzen einen Pullup gegen
VCC (also eigentlich sinds auf jeder Leitung zwei Pullups, masterseitig
10k Ohm und slaveseitig 4k7 Ohm - ergibt also 3,19k Ohm)