Forum: Mikrocontroller und Digitale Elektronik stm32f100 I2C bricht nach 2. Startsignal ab


von Martin (Gast)


Angehängte Dateien:

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
}

von Martin (Gast)


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 ;)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.