Forum: Mikrocontroller und Digitale Elektronik Cortex M3 I2C timingproblem


von Sylvia H. (sandy)


Lesenswert?

Hi Leute, ich habe ein Timingproblem bei der Programmierung des I2C Bus 
des Cortex M3:
Ich flashe das Programm mit Eqlipse im Debugmodus auf meinen Cortex. Das 
Ergebnis schaue ich mir mit Hilfe des ARRDVARK auf meinem Rechner an. 
Wenn ich nun in meinem GoEther() Task über den I2C Bus ein Datenarray 
verschicken möchte, dann funktioniert es nur, wenn ich nach jedem Byte 
eine kleine Wartezeit einbaue. Das verstehe ich schon mal nicht so 
richtig. Das wirkliche seltsame ist aber, dass das Programm nicht läuft, 
sobald ich den Controller "alleine" starte, also mit Reset, oder einfach 
so an die Spannung anschliesse. Es funktioniert nur, direkt nach dem 
Eqlipse flashen.
Hat jemand eine Erklärung dafür?
Zum Code:
ich poste meinen gesammten Code, nicht wundern, ich möchte mit meinem 
Controller später noch  einen ENC28J60 ansteuern, zusätzlich spielt CAN 
auch noch eine Rolle. Deshalb sind da Codefragmente darin, die nichts 
mit I2C zu tun haben, ich dachte mir aber ich lasse mal alles drinn, 
vielleicht spielen sie eine Rolle für das Timing....

Hier die I2C Codes:
1
/**
2
  * @brief  Initialize all stuff you need for I2C
3
  * @retval None.
4
  */
5
void I2C_config(void)
6
{
7
  I2C_InitTypeDef  I2C_InitStructure1;
8
  I2C_InitTypeDef  I2C_InitStructure2;
9
10
 //zuerste I2C1 initialisieren------------------------------------------------
11
  I2C_DeInit(I2C1);
12
13
  /* I2C configuration */
14
  I2C_InitStructure1.I2C_Mode = I2C_Mode_I2C;
15
  I2C_InitStructure1.I2C_DutyCycle = I2C_DutyCycle_2;
16
  I2C_InitStructure1.I2C_OwnAddress1 = I2C1_SLAVE_ADDRESS7;
17
  I2C_InitStructure1.I2C_Ack = I2C_Ack_Enable;
18
  I2C_InitStructure1.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
19
  I2C_InitStructure1.I2C_ClockSpeed = I2C_Speed;
20
21
22
  /* Apply I2C configuration (war in der vorlage erst nach I2C_Cmd()) */
23
  I2C_Init(I2C1, &I2C_InitStructure1);
24
  /* I2C Peripheral Enable */
25
  I2C_Cmd(I2C1, ENABLE);
26
27
  //GPIO Configs
28
  GPIO_InitTypeDef  GPIO_InitStructure1;
29
30
   /* GPIOB clock enable */
31
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //??????????????wurde schon bei SPI Init erledigt
32
    /* I2C1 clock enable */
33
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
34
35
   /* Configure I2C1 pins: SCL and SDA to communicate with outside */
36
   GPIO_InitStructure1.GPIO_Pin =  GPIO_Pin_6 | GPIO_Pin_7;
37
   GPIO_InitStructure1.GPIO_Speed = GPIO_Speed_50MHz;
38
   GPIO_InitStructure1.GPIO_Mode = GPIO_Mode_AF_OD;
39
   GPIO_Init(GPIOB, &GPIO_InitStructure1);
40
41
42
   //danach I2C2 initialisieren------------------------------------------------
43
   I2C_DeInit(I2C2);
44
45
   // GPIOB clock enable  wurde oben schon erledigt
46
       // RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
47
       // I2C2 clock enable
48
       RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);
49
50
    // I2C configuration
51
    I2C_InitStructure2.I2C_Mode = I2C_Mode_I2C;
52
    I2C_InitStructure2.I2C_DutyCycle = I2C_DutyCycle_2;
53
    I2C_InitStructure2.I2C_OwnAddress1 = I2C2_SLAVE_ADDRESS7;
54
    I2C_InitStructure2.I2C_Ack = I2C_Ack_Enable;
55
    I2C_InitStructure2.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
56
    I2C_InitStructure2.I2C_ClockSpeed = I2C_Speed;
57
58
    //Apply I2C configuration (war in der vorlage erst nach I2C_Cmd())
59
     I2C_Init(I2C2, &I2C_InitStructure2);
60
     // I2C Peripheral Enable
61
     I2C_Cmd(I2C2, ENABLE);
62
63
     //GPIO Configs
64
      GPIO_InitTypeDef  GPIO_InitStructure2;
65
66
67
68
   // Configure I2C2 pins: SCL and SDA for the administrative bus
69
    GPIO_InitStructure2.GPIO_Pin =  GPIO_Pin_10 | GPIO_Pin_11;
70
    GPIO_InitStructure2.GPIO_Speed = GPIO_Speed_50MHz;
71
    GPIO_InitStructure2.GPIO_Mode = GPIO_Mode_AF_OD;
72
    GPIO_Init(GPIOB, &GPIO_InitStructure2);
73
74
75
}
76
77
78
/**
79
  * @brief  Transmits one byte to  the  selected slave device.
80
  * @param  I2Cx: where x can be 1 or 2 to select the I2C peripheral.
81
  * @param  Address: specifies the slave address to which the data will be transmitted
82
  * @param  Data: the data byte which will be transmitted
83
  * @retval None.
84
  */
85
void I2C_Master_Transmit_Byte(I2C_TypeDef* I2Cx, uint8_t Adress, uint8_t Data)
86
{
87
  if(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY))
88
     I2C_GenerateSTOP(I2C1, ENABLE);
89
90
  // I2Cx->CR1 = 0xC01; /* ACK=1, POS =1, PE = 1  */
91
    /* Send STRAT condition */
92
      I2C_GenerateSTART(I2Cx, ENABLE);
93
94
       /* Test on EV5 and clear it */
95
      while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
96
97
      I2C_Send7bitAddress(I2C1, Adress, I2C_Direction_Transmitter);
98
99
      /* Test on EV6 and clear it */
100
       while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
101
102
       /*Send Data*/
103
       I2C_SendData(I2C1,Data);
104
105
       /* Test on EV8 and clear it */
106
      while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING));
107
108
      /* Test on EV8_2 and clear it */
109
       //    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
110
111
      /* Send STOP condition */
112
         I2C_GenerateSTOP(I2C1, ENABLE);
113
}

und hier meine main:
1
#include "stm32f10x.h"
2
#include "FreeRTOSSource/FreeRTOS.h"
3
#include "FreeRTOSSource/task.h"
4
#include "lib/can.h"
5
#include "lib/outpin.h"
6
#include "lib/canids.h"
7
#include "lib/i2c.h"
8
#include "Std_lib/misc.h"
9
#include "Std_lib/stm32f10x_it.h"
10
#include "Std_lib/stm32f10x_rcc.h"
11
#include "Std_lib/stm32f10x_dma.h"
12
#include "lib/SPI.H"
13
14
#include "lib/enc28j60.h"
15
16
17
const unsigned char enc28j60_MAC[6] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06};
18
/**
19
 * FreeRTOS task prototypes.
20
 */
21
22
portTASK_FUNCTION(goEther, param);
23
24
25
portTASK_FUNCTION(vQueryCAN, param);
26
27
portTASK_FUNCTION(vBlinkLEDs, param);
28
29
/* Private define ------------------------------------------------------------*/
30
31
32
/* Private macro -------------------------------------------------------------*/
33
/* Private variables ---------------------------------------------------------*/
34
35
DMA_InitTypeDef DMA_InitStructure;
36
37
38
volatile portTickType lastErrorTimeStamp;
39
outpin_t led_ready, led_error, led_3,led_4, ready,sck;
40
41
42
/**
43
  * @brief  Configures NVIC and Vector Table base location.
44
  * @param  None
45
  * @retval : None
46
  */
47
void NVIC_Configuration(void)
48
{
49
50
    /* 1 bit for pre-emption priority, 3 bits for subpriority */
51
  //  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
52
53
    NVIC_SetPriority(I2C1_EV_IRQn, 0x00);
54
    NVIC_EnableIRQ(I2C1_EV_IRQn);
55
56
    NVIC_SetPriority(I2C1_ER_IRQn, 0x01);
57
    NVIC_EnableIRQ(I2C1_ER_IRQn);
58
59
60
    NVIC_SetPriority(I2C2_EV_IRQn, 0x00);
61
    NVIC_EnableIRQ(I2C2_EV_IRQn);
62
63
    NVIC_SetPriority(I2C2_ER_IRQn, 0x01);
64
    NVIC_EnableIRQ(I2C2_ER_IRQn);
65
66
}
67
68
69
70
71
///////////////////////////////////////////////////////////////////////////////
72
// MAIN
73
///////////////////////////////////////////////////////////////////////////////
74
int main(void) {
75
76
  outpin_init(&led_ready, 'C', 0);
77
  outpin_init(&ready, 'C', 14);
78
  outpin_init(&led_3, 'C', 2);
79
  outpin_init(&led_4, 'C', 3);
80
  outpin_init(&led_error, 'C', 1);
81
82
83
  // this sets up the oscilator
84
  SystemInit();
85
  // Initialization
86
  NVIC_Configuration();
87
  CAN_inits();
88
  SPI2_Init();
89
  I2C_config();
90
91
92
         //zu testzwecken
93
    outpin_enable(&led_3);
94
    outpin_enable(&led_4);
95
    outpin_enable(&led_error);
96
    
97
98
  enc28j60Init((unsigned char *)enc28j60_MAC);
99
100
    
101
102
  enc_powerdown();
103
104
  //initialization terminated
105
  outpin_enable(&ready);
106
107
  // launch CAN query task one priority level below
108
  xTaskCreate(vQueryCAN, (const int8_t*)"QCAN", 100, NULL, tskIDLE_PRIORITY, NULL);
109
  // launch blink
110
  xTaskCreate(vBlinkLEDs, (const int8_t*)"BLINK", 100, NULL, tskIDLE_PRIORITY, NULL);
111
112
113
  xTaskCreate(goEther, (const int8_t*)"Ether", 200, NULL, tskIDLE_PRIORITY, NULL);
114
115
  vTaskStartScheduler();
116
  return 0;
117
}
118
119
120
portTASK_FUNCTION(goEther, param) {
121
  outpin_t CS_Ether, MOSI, SCK;
122
  outpin_init(&CS_Ether, 'B', 12); // SS Ethernetmodul
123
124
  uint8_t buffer[16] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F};
125
126
    int i;
127
128
  for (i = 0;i<=15;i++)
129
  {
130
    int a = 1000;
131
         while(--a);
132
    I2C_Master_Transmit_Byte(I2C1,0x00,buffer[i]);
133
  }
134
135
  while (1) {
136
    
137
138
  }
139
140
}
141
142
143
/**
144
 * This task grabs actor messages from the CAN bus and forwards their
145
 * content.
146
 * ERROR messages are also evaluated.
147
 */portTASK_FUNCTION(vQueryCAN, param) {
148
  // Register all CAN ids that could contain interesting
149
  // messages.
150
151
  CAN_subscribeId(CANID_ERROR);
152
153
  uint32_t message;
154
  static float norm;
155
  static uint8_t brake;
156
  static portTickType timeStamp;
157
158
  while (1) {
159
    timeStamp = xTaskGetTickCount();
160
161
    if (CAN_receive(CANID_ERROR, &message)) {
162
      if (message == ERRORID_PWM_FREQUENCY || message
163
          == ERRORID_PWM_OUTOFBOUNDS || message
164
          == ERRORID_RECEIVER_NOSIGNAL)
165
        lastErrorTimeStamp = timeStamp;
166
    }
167
    // and sleep for 10ms before trying to fetch new messages again
168
    vTaskDelay(10 / portTICK_RATE_MS);
169
  }
170
}
171
/**
172
 * Task to blink the "RUNS" LED
173
 * Slow blinking for normal operation, fast for indicating some error.
174
 */portTASK_FUNCTION(vBlinkLEDs, param) {
175
176
177
  //outpin_init(&led_ready, 'C', 0);
178
  while (1) {
179
    outpin_toggle(&led_ready);
180
    if (xTaskGetTickCount() - lastErrorTimeStamp > 1000 / portTICK_RATE_MS) {
181
      // blink slow if ok
182
      vTaskDelay(250 / portTICK_RATE_MS);
183
      //for(int i=0;i<0xffff;i++){
184
185
186
    } else {
187
      // hectic blink if error present now or in the last second
188
      //for(int i=0;i<0xffff;i++);
189
      vTaskDelay(75 / portTICK_RATE_MS);
190
191
    }
192
  }
193
}

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.