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 | }
|