stm32f100 I2C bricht nach 2. Startsignal ab

Gast #4078005
Lesenswert?
• ▲
▼
Hi
Ich versuche gerade eine i2c Verbindung aufzubauen, was an sich auch 
schon was tut.
Wenn ich mein Programm starte, macht es das, was es soll. Es generiert 
ein Startsignal, überträgt die Adresse und sendet Daten.
Sobald aber das zweite Startsignal erzeugt wird, springt mein Programm 
einmal in den Interrupt, liest das SR1 und schreibt die Adresse in das 
Datenregister. Danach passiert nichts mehr. Also er sendet die Adresse 
nicht und springt auch nicht mehr in mein Interrupt. Statt dessen wird 
gleich wieder ein Stoppsignal generiert.
Im angehängten Bild sieht man was ich meine.

Ich hoffe mir kann jemand helfen, ich bin nämlich schon am verzweifeln!
Wer noch mehr Infos braucht, einfach sagen.


Mein Code:

1
#include "i2c.h"
2

3

4
static uint8_t i2c_slave_address_buffer = 0;
5
static uint8_t* i2c_data_buffer;
6
static uint8_t data_length = 0;
7
static uint8_t i2c_direction = I2C_Direction_Receiver;
8

9

10
void i2c_init(){
11
  GPIO_InitTypeDef GPIO_InitStructure;
12
  NVIC_InitTypeDef NVIC_InitStructure;
13
  I2C_InitTypeDef I2C_InitStructure;
14
  
15
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
16
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
17
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);
18
  
19
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
20
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
21
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
22
  GPIO_Init(GPIOB, &GPIO_InitStructure);
23
  
24
  NVIC_InitStructure.NVIC_IRQChannel = I2C2_EV_IRQn;
25
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
26
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
27
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
28
  NVIC_Init(&NVIC_InitStructure);
29
  
30
  NVIC_InitStructure.NVIC_IRQChannel = I2C2_ER_IRQn;
31
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
32
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
33
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
34
  NVIC_Init(&NVIC_InitStructure);
35
  
36
  I2C_DeInit(I2C2);
37
  
38
  I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
39
  I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
40
  I2C_InitStructure.I2C_ClockSpeed = 100000;
41
  I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
42
  I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
43
  I2C_InitStructure.I2C_OwnAddress1 = 0;
44
  I2C_Init(I2C2, &I2C_InitStructure);
45
  
46
  I2C_ITConfig(I2C2, I2C_IT_EVT, ENABLE);
47
  I2C_ITConfig(I2C2, I2C_IT_BUF, ENABLE);
48
  I2C_ITConfig(I2C2, I2C_IT_ERR, ENABLE);
49
  
50
  I2C_Cmd(I2C2, ENABLE);
51
}
52

53

54
void i2c_transmitt_data(uint8_t slave_address, uint8_t* data, uint8_t length, uint8_t direction){
55
  while(I2C_GetFlagStatus(I2C2, I2C_FLAG_BUSY));
56
  i2c_slave_address_buffer = slave_address;
57
  i2c_data_buffer = data;
58
  i2c_direction = direction;
59
  data_length = length;
60
  I2C_AcknowledgeConfig(I2C2, ENABLE);
61
  I2C_GenerateSTART(I2C2, ENABLE);
62
}
63

64

65
void show_error(){
66
  if(I2C_GetFlagStatus(I2C2, I2C_FLAG_BERR)) send_display(2, 1, "BEER");
67
  if(I2C_GetFlagStatus(I2C2, I2C_FLAG_ARLO)) send_display(2, 6, "ARLO");
68
  if(I2C_GetFlagStatus(I2C2, I2C_FLAG_AF)) send_display(2, 11, "AF");
69
  if(I2C_GetFlagStatus(I2C2, I2C_FLAG_OVR)) send_display(2, 14, "OVR");
70
  if(I2C_GetFlagStatus(I2C2, I2C_FLAG_PECERR)) send_display(3, 1, "PECERR");
71
  if(I2C_GetFlagStatus(I2C2, I2C_FLAG_TIMEOUT)) send_display(3, 8, "TIMEOUT");
72
}
73

74

75
void I2C2_EV_IRQHandler(void){
76
  if(I2C_GetFlagStatus(I2C2, I2C_FLAG_SB)){
77
    I2C2->DR = (i2c_slave_address_buffer << 1) | i2c_direction;
78
    if(data_length == 1 && !I2C_GetFlagStatus(I2C2, I2C_FLAG_TRA)){
79
      //I2C_AcknowledgeConfig(I2C2, DISABLE);
80
      //I2C_GenerateSTOP(I2C2, ENABLE); 
81
    }
82
  }
83
  else if(I2C_GetFlagStatus(I2C2, I2C_FLAG_RXNE) && !I2C_GetFlagStatus(I2C2, I2C_FLAG_TRA)){
84
    *i2c_data_buffer++ = I2C2->DR;
85
    if(data_length == 0){
86
      I2C_AcknowledgeConfig(I2C2, DISABLE);
87
      I2C_GenerateSTOP(I2C2, ENABLE);    
88
    }
89
    --data_length;
90
  }
91
  //else if(I2C_GetFlagStatus(I2C2, I2C_FLAG_ADDR)){
92
  else if(I2C_GetFlagStatus(I2C2, I2C_FLAG_TXE) && I2C_GetFlagStatus(I2C2, I2C_FLAG_TRA)){
93
    if(data_length > 0){
94
      I2C2->DR = *i2c_data_buffer++;
95
      //++i2c_data_buffer;
96
      --data_length;
97
    }
98
    else I2C_GenerateSTOP(I2C2, ENABLE);
99
  }
100
  else{
101
    //I2C_GenerateSTOP(I2C2, ENABLE);
102
  }
103
  //if((I2C2->SR1&0x0DF00)>0){
104
    //show_error();
105
  //}
106

107
}
108

109

110
void I2C2_ER_IRQHandler(void){
111
  show_error();
112
}
113

114

115

116

117
int main() {
118
  display_init();
119
  i2c_init();
120
  
121
  data_buffer[0] = 0x00;
122
  data_buffer[1] = 0x19;
123
  data_buffer[2] = 0xee;
124
  data_buffer[3] = 0x0a;
125
  data_buffer[4] = 0x05;
126
  i2c_transmitt_data(0x29, data_buffer, 5, I2C_Direction_Transmitter);
127
  i2c_transmitt_data(0x29, data_buffer, 5, I2C_Direction_Transmitter);
128
  //i2c_transmitt_data(0x29, data_buffer, 1, I2C_Direction_Receiver);
129
  
130
  send_display(1, 1, "wert:");
131
  delay_ms(1);
132
  to_array(data_buffer[0]);
133
  send_display(1, 7, display_buffer);
134
}
Angehängte Dateien:
Gast #4080536
Lesenswert?
• ▲
▼
Ich hab mein Problem mittlerweile gelöst.
Die Lösung:
Ich hab mein Programm einfach mal meinem Vater gezeigt, dann hat es 
spontan entschieden zumindest im Debugger das zu tun, was ich wollte.
Naja, ich hab dann in dem Interrupt noch eine Verzögerung eingebaut und 
jetzt funktioniert es wunderbar. Wieso ich die brauch, ist mir 
allerdings schleierhaft.
Hatte das aber schon mal im Studium. Da hab ich (auf dem gleichen Chip) 
einen Timer programmiert und musste noch eine sinnlose Wert Zuweisung 
einbauen, weil es sonst nicht funktioniert hat. Selbst mein Prof hatte 
keine Ahnung, was das war...
Wer also weis, wieso das so ist, möge doch bitte sein Wissen Teilen ;)

Antwort schreiben

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.