Forum: Mikrocontroller und Digitale Elektronik STM32F107VC, CAN Neuling, Beispiel oder Hilfe gesucht


von Mark (Gast)


Lesenswert?

Hallo, ich versuche gerade den CAN des STM32F107VC zum laufen zu bringen 
und habe dazu mal ein ST-Beispiel angepasst, da die ja auf bestimmte 
Eval Boards ausgelegt sind. Allerdings funktioniert hier überhaupt 
nichts bzw. ich bin Anfänger und habe keine Ahnungt vom CAN. Ich dachte 
dass bei korrekter Funktion vom TX Pin ein Signal ausgehen würde. Ein 
Transciever ist noch nicht angeschlossen. Kann mir jemand helfen oder 
mich auf ein konkretes Beispiel verweisen? Ich hänge mal den Code an. 
Danke

main:
1
/* Includes ------------------------------------------------------------------*/
2
#include "stm32f10x.h"
3
4
/* Private define ------------------------------------------------------------*/
5
//#define __CAN1_USED__
6
 #define __CAN2_USED__*/   /* Please check that you device is
7
                                Connectivity line when using CAN2 */
8
9
#ifdef  __CAN1_USED__
10
  #define CANx CAN1
11
#else /*__CAN2_USED__*/
12
  #define CANx CAN2
13
#endif  /* __CAN1_USED__ */
14
15
/* Private typedef -----------------------------------------------------------*/
16
typedef enum {FAILED = 0, PASSED = !FAILED} TestStatus;
17
/* Private macro -------------------------------------------------------------*/
18
/* Private variables ---------------------------------------------------------*/
19
__IO uint32_t ret = 0; /* for return of the interrupt handling */
20
volatile TestStatus TestRx;
21
22
/* Private function prototypes -----------------------------------------------*/
23
void NVIC_Configuration(void);
24
TestStatus CAN_Polling(void);
25
TestStatus CAN_Interrupt(void);
26
27
/* Private functions ---------------------------------------------------------*/
28
29
  
30
int main(void)
31
{
32
33
34
    /* CAN1 Periph clock enable */
35
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
36
37
//  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
38
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
39
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
40
41
42
43
GPIO_InitTypeDef GPIO_InitStructure;
44
45
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
46
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
47
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
48
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;
49
    GPIO_Init(GPIOC, &GPIO_InitStructure);
50
51
    // Configure CAN Tx as push-pull
52
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
53
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
54
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
55
      GPIO_Init(GPIOB, &GPIO_InitStructure);
56
    // Configure CAN Rx as input floating
57
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
58
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
59
      GPIO_Init(GPIOB, &GPIO_InitStructure);
60
61
62
#ifdef  __CAN1_USED__
63
  /* CANx Periph clock enable */
64
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
65
#else /*__CAN2_USED__*/
66
  /* CAN1 & 2  Periph clock enable */
67
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
68
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN2, ENABLE);
69
#endif  /* __CAN1_USED__ */
70
71
  /* NVIC Configuration */
72
  NVIC_Configuration();
73
74
75
  /* CAN transmit at 125Kb/s and receive by polling in loopback mode */
76
  TestRx = CAN_Polling();
77
78
  if (TestRx == FAILED)
79
  {
80
    /* Turn on led LD3 */
81
   // STM_EVAL_LEDOn(LED3);
82
83
  GPIO_WriteBit(GPIOC, GPIO_Pin_6, Bit_SET);
84
85
  }
86
  else
87
  {
88
    /* Turn on led LD1 */
89
    //STM_EVAL_LEDOn(LED1);
90
    GPIO_WriteBit(GPIOC, GPIO_Pin_6, Bit_RESET);
91
92
  }
93
94
  /* CAN transmit at 500Kb/s and receive by interrupt in loopback mode */
95
  TestRx = CAN_Interrupt();
96
97
  if (TestRx == FAILED)
98
  {
99
    /* Turn on led LD4 */
100
   //STM_EVAL_LEDOn(LED4);
101
    GPIO_WriteBit(GPIOC, GPIO_Pin_7, Bit_SET);
102
  }
103
  else
104
  {
105
    /* Turn on led LD2 */
106
   // STM_EVAL_LEDOn(LED2);
107
    GPIO_WriteBit(GPIOC, GPIO_Pin_7, Bit_RESET);
108
  }
109
110
  /* Infinite loop */
111
  while (1)
112
  {
113
114
115
  }
116
}
117
118
/**
119
  * @brief  Configures the CAN, transmit and receive by polling
120
  * @param  None
121
  * @retval PASSED if the reception is well done, FAILED in other case
122
  */
123
TestStatus CAN_Polling(void)
124
{
125
  CAN_InitTypeDef        CAN_InitStructure;
126
  CAN_FilterInitTypeDef  CAN_FilterInitStructure;
127
  CanTxMsg TxMessage;
128
  CanRxMsg RxMessage;
129
  uint32_t i = 0;
130
  uint8_t TransmitMailbox = 0;
131
132
  /* CAN register init */
133
  CAN_DeInit(CANx);
134
135
  CAN_StructInit(&CAN_InitStructure);
136
137
  /* CAN cell init */
138
  CAN_InitStructure.CAN_TTCM=DISABLE;
139
  CAN_InitStructure.CAN_ABOM=DISABLE;
140
  CAN_InitStructure.CAN_AWUM=DISABLE;
141
  CAN_InitStructure.CAN_NART=DISABLE;
142
  CAN_InitStructure.CAN_RFLM=DISABLE;
143
  CAN_InitStructure.CAN_TXFP=DISABLE;
144
  CAN_InitStructure.CAN_Mode=CAN_Mode_LoopBack;
145
146
  /* Baudrate = 125kbps*/
147
  CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;
148
  CAN_InitStructure.CAN_BS1=CAN_BS1_2tq;
149
  CAN_InitStructure.CAN_BS2=CAN_BS2_3tq;
150
  CAN_InitStructure.CAN_Prescaler=48;
151
  CAN_Init(CANx, &CAN_InitStructure);
152
153
  /* CAN filter init */
154
#ifdef  __CAN1_USED__
155
  CAN_FilterInitStructure.CAN_FilterNumber=0;
156
#else /*__CAN2_USED__*/
157
  CAN_FilterInitStructure.CAN_FilterNumber=14;
158
#endif  /* __CAN1_USED__ */
159
  CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;
160
  CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;
161
  CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;
162
  CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
163
  CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;
164
  CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
165
  CAN_FilterInitStructure.CAN_FilterFIFOAssignment=0;
166
167
168
  CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;
169
  CAN_FilterInit(&CAN_FilterInitStructure);
170
171
  /* transmit */
172
  TxMessage.StdId=0x11;
173
  TxMessage.RTR=CAN_RTR_DATA;
174
  TxMessage.IDE=CAN_ID_STD;
175
  TxMessage.DLC=2;
176
  TxMessage.Data[0]=0xCA;
177
  TxMessage.Data[1]=0xFE;
178
179
  TransmitMailbox=CAN_Transmit(CANx, &TxMessage);
180
  i = 0;
181
  while((CAN_TransmitStatus(CANx, TransmitMailbox) != CANTXOK) && (i != 0xFFFF))
182
  {
183
    i++;
184
  }
185
186
  i = 0;
187
  while((CAN_MessagePending(CANx, CAN_FIFO0) < 1) && (i != 0xFFFF))
188
  {
189
    i++;
190
  }
191
192
  /* receive */
193
  RxMessage.StdId=0x00;
194
  RxMessage.IDE=CAN_ID_STD;
195
  RxMessage.DLC=0;
196
  RxMessage.Data[0]=0x00;
197
  RxMessage.Data[1]=0x00;
198
  CAN_Receive(CANx, CAN_FIFO0, &RxMessage);
199
200
  if (RxMessage.StdId!=0x11)
201
  {
202
    return FAILED;
203
  }
204
205
  if (RxMessage.IDE!=CAN_ID_STD)
206
  {
207
    return FAILED;
208
  }
209
210
  if (RxMessage.DLC!=2)
211
  {
212
    return FAILED;
213
  }
214
215
  if ((RxMessage.Data[0]<<8|RxMessage.Data[1])!=0xCAFE)
216
  {
217
    return FAILED;
218
  }
219
220
  return PASSED; /* Test Passed */
221
}
222
223
/**
224
  * @brief  Configures the CAN, transmit and receive using interrupt.
225
  * @param  None
226
  * @retval PASSED if the reception is well done, FAILED in other case
227
  */
228
TestStatus CAN_Interrupt(void)
229
{
230
  CAN_InitTypeDef        CAN_InitStructure;
231
  CAN_FilterInitTypeDef  CAN_FilterInitStructure;
232
  CanTxMsg TxMessage;
233
  uint32_t i = 0;
234
235
  /* CAN register init */
236
  CAN_DeInit(CANx);
237
238
239
  CAN_StructInit(&CAN_InitStructure);
240
241
  /* CAN cell init */
242
  CAN_InitStructure.CAN_TTCM=DISABLE;
243
  CAN_InitStructure.CAN_ABOM=DISABLE;
244
  CAN_InitStructure.CAN_AWUM=DISABLE;
245
  CAN_InitStructure.CAN_NART=DISABLE;
246
  CAN_InitStructure.CAN_RFLM=DISABLE;
247
  CAN_InitStructure.CAN_TXFP=DISABLE;
248
  CAN_InitStructure.CAN_Mode=CAN_Mode_LoopBack;
249
  CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;
250
251
  /* Baudrate = 500 Kbps */
252
  CAN_InitStructure.CAN_BS1=CAN_BS1_2tq;
253
  CAN_InitStructure.CAN_BS2=CAN_BS2_3tq;
254
  CAN_InitStructure.CAN_Prescaler=12;
255
  CAN_Init(CANx, &CAN_InitStructure);
256
257
  /* CAN filter init */
258
#ifdef  __CAN1_USED__
259
  CAN_FilterInitStructure.CAN_FilterNumber=1;
260
#else /*__CAN2_USED__*/
261
  CAN_FilterInitStructure.CAN_FilterNumber=15;
262
#endif  /* __CAN1_USED__ */
263
  CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;
264
  CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;
265
  CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;
266
  CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
267
  CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;
268
  CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
269
  CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_FIFO0;
270
  CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;
271
  CAN_FilterInit(&CAN_FilterInitStructure);
272
273
  /* CAN FIFO0 message pending interrupt enable */
274
  CAN_ITConfig(CANx, CAN_IT_FMP0, ENABLE);
275
276
  /* transmit 1 message */
277
  TxMessage.StdId=0;
278
  TxMessage.ExtId=0x1234;
279
  TxMessage.IDE=CAN_ID_EXT;
280
  TxMessage.RTR=CAN_RTR_DATA;
281
  TxMessage.DLC=2;
282
  TxMessage.Data[0]=0xDE;
283
  TxMessage.Data[1]=0xCA;
284
  CAN_Transmit(CANx, &TxMessage);
285
286
  /* initialize the value that will be returned */
287
  ret = 0xFF;
288
289
  /* receive message with interrupt handling */
290
  i=0;
291
  while((ret == 0xFF) && (i < 0xFFF))
292
  {
293
    i++;
294
  }
295
296
  if (i == 0xFFF)
297
  {
298
    ret=0;
299
  }
300
301
  /* disable interrupt handling */
302
  CAN_ITConfig(CANx, CAN_IT_FMP0, DISABLE);
303
304
  return (TestStatus)ret;
305
}
306
307
/**
308
  * @brief  Configures the NVIC and Vector Table base address.
309
  * @param  None
310
  * @retval None
311
  */
312
void NVIC_Configuration(void)
313
{
314
  NVIC_InitTypeDef NVIC_InitStructure;
315
316
  /* Enable CANx RX0 interrupt IRQ channel */
317
#ifndef STM32F10X_CL
318
319
#ifdef  __CAN1_USED__
320
  NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;
321
#else  /*__CAN2_USED__*/
322
  /* CAN2 is not implemented in the device */
323
   #error "CAN2 is implemented only in Connectivity line devices"
324
325
#endif /*__CAN1_USED__*/
326
#else
327
#ifdef  __CAN1_USED__
328
  NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn;
329
#else  /*__CAN2_USED__*/
330
  NVIC_InitStructure.NVIC_IRQChannel = CAN2_RX0_IRQn;
331
#endif /*__CAN1_USED__*/
332
333
#endif /* STM32F10X_CL*/
334
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
335
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
336
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
337
  NVIC_Init(&NVIC_InitStructure);
338
}
339
340
#ifdef  USE_FULL_ASSERT
341
342
/**
343
  * @brief  Reports the name of the source file and the source line number
344
  *         where the assert_param error has occurred.
345
  * @param  file: pointer to the source file name
346
  * @param  line: assert_param error line source number
347
  * @retval None
348
  */
349
void assert_failed(uint8_t* file, uint32_t line)
350
{
351
  /* User can add his own implementation to report the file name and line number,
352
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
353
354
  /* Infinite loop */
355
  while (1)
356
  {
357
  }
358
}
359
360
#endif
361
362
/**
363
  * @}
364
  */
365
366
/**
367
  * @}
368
  */
369
370
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/



ISR
1
  */
2
#ifndef STM32F10X_CL
3
void USB_LP_CAN1_RX0_IRQHandler(void)
4
#else
5
void CAN1_RX0_IRQHandler(void)
6
#endif
7
{
8
  CanRxMsg RxMessage;
9
10
  RxMessage.StdId=0x00;
11
  RxMessage.ExtId=0x00;
12
  RxMessage.IDE=0;
13
  RxMessage.DLC=0;
14
  RxMessage.FMI=0;
15
  RxMessage.Data[0]=0x00;
16
  RxMessage.Data[1]=0x00;
17
18
  CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);
19
20
  if((RxMessage.ExtId==0x1234) && (RxMessage.IDE==CAN_ID_EXT)
21
     && (RxMessage.DLC==2) && ((RxMessage.Data[1]|RxMessage.Data[0]<<8)==0xDECA))
22
  {
23
    ret = 1;
24
  }
25
  else
26
  {
27
    ret = 0;
28
  }
29
}
30
31
/**
32
  * @brief  This function handles CAN2 Handler.
33
  * @param  None
34
  * @retval None
35
  */
36
#ifdef STM32F10X_CL
37
void CAN2_RX0_IRQHandler(void)
38
39
{
40
  CanRxMsg RxMessage;
41
42
  RxMessage.StdId=0x00;
43
  RxMessage.ExtId=0x00;
44
  RxMessage.IDE=0;
45
  RxMessage.DLC=0;
46
  RxMessage.FMI=0;
47
  RxMessage.Data[0]=0x00;
48
  RxMessage.Data[1]=0x00;
49
50
  CAN_Receive(CAN2, CAN_FIFO0, &RxMessage);
51
52
  if((RxMessage.ExtId==0x1234) && (RxMessage.IDE==CAN_ID_EXT)
53
     && (RxMessage.DLC==2) && ((RxMessage.Data[1]|RxMessage.Data[0]<<8)==0xDECA))
54
  {
55
    ret = 1;
56
  }
57
  else
58
  {
59
    ret = 0;
60
  }
61
}
62
#endif
von Matthias (Gast)


Lesenswert?

Mark schrieb:
> ich bin Anfänger und habe keine Ahnungt vom CAN.

Wie willst Du dann eine CAN Anwendung programmieren?

Erstmal solltest Du Dich mit CAN allgemein beschäftigen. Dann eine LED 
auf den Board zum blinken bringen...
von Markus M. (Firma: EleLa - www.elela.de) (mmvisual)


Lesenswert?

> Ich dachte dass bei korrekter Funktion vom TX Pin ein Signal ausgehen
> würde.

Falsch gedacht. Es braucht immer einen Empfänger, der NICHT im 
"ListenOnly" Modus betrien wird.
von Volker Z. (vza)


Lesenswert?

> Ich dachte dass bei korrekter Funktion vom TX Pin ein Signal ausgehen
> würde.

Dies ist (fast) richtig:
Hast du keinen Tranceifer/keinen Gegenspieler sollte der CAN-Kontroller
das Paket ein paar mal senden (jeweils mit einem Errorframe angehängt)
und dann in den BUS-OFF Zustand wechseln. Dies geht sehr schnell.

Vielleicht hilft dir auch dieser Beitrag:
Beitrag "CAN Problem Freescale S12X"
von Mark (Gast)


Lesenswert?

Danke, ich denke das könnte helfen. Ich habe mich natürlich etwas mit 
der Theorie beschäftigt, also welche Pakete werden verschickt bzw. wie 
sind die Frames aufgebaut ect. Aber ich habe halt noch nie einen auf 
einem µC programmiert und habe dahingehend keine Ahnung. Das meinte ich. 
Auch dachte ich, den den Controller dazu zwingen kann die Botschaft 
mittels einer Schleife ständig zu senden, so dass man ein Signal sehen 
kann, auch ohne Transceiver . Ich wollte ja noch nichts konkretes 
auslesen, sonder im ersten Schritt nur mal etwas zappeln sehen. Ich 
versuchs noch mal mit dem Transceiver.. sobald er da ist.

Ich habs doch gerade noch mal schnell durchlaufen lassen. Du hast recht, 
am Anfang kommt wirklich ein Paket. Wie gesagt ich dachte ich könnte ihn 
zwingen das öfter zu schicken durch mehrmaligen Aufruf.


Ich meine mal gelesen zu haben dass man sich auf kurzen Strecken den 
Transceiver schenken kann. Also zum Testen auf wenigen cm z.B. Hat 
dahingehend jemand Erfahrungen?
von Peterle (Gast)


Lesenswert?

Ja, an dem TX-Pin solltest Du etwas sehen können. Misst Du an der 
richtigen Stelle? Die CAN-Funktion kann, soweit ich weiß, an 
unterschiedliche Pins des STM gemappt werden.
von Mark (Gast)


Lesenswert?

Ja, wie gesagt ich habe es erst später gesehen. Da ich von einer 
Widerholung ausgegangen bin habe ich das Programm gestartet und dann 
erst die Oszispitze an den Pin gehalten bzw. Mich auf die Triggerung 
verlassen die Wiederholte Signale darstellen sollte.
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.