1 /*
2  * Copyright (c) 2006-2018, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2018-01-06     sundm75       first version
9  */
10 
11 #include "ls1c.h"
12 #include "ls1c_public.h"
13 #include "ls1c_can.h"
14 #include "ls1c_delay.h"
15 
set_reset_mode(CAN_TypeDef * CANx)16 unsigned char  set_reset_mode(CAN_TypeDef* CANx)
17 {
18   unsigned char status;
19   int i;
20 
21   /*检查复位标志*/
22   status = CANx->MOD;
23 
24   /* 关闭中断 */
25   CANx->IER = 0x00;
26 
27   for (i = 0; i < 100; i++)
28   {
29     if((status & CAN_Mode_RM) == CAN_Mode_RM)
30         return 1;
31 
32     /* 设置复位*/
33     CANx->MOD |=  ((unsigned char)CAN_Mode_RM);
34 
35     /*延时*/
36     delay_us(10);
37 
38     /*检查复位标志*/
39     status = CANx->MOD;
40   }
41   printf("\r\nSetting SJA1000 into reset mode failed!\r\n");
42   return 0;
43 }
44 
set_normal_mode(CAN_TypeDef * CANx)45 static unsigned char  set_normal_mode(CAN_TypeDef* CANx)
46 {
47   unsigned char status;
48   int i;
49 
50   /*检查复位标志*/
51   status = CANx->MOD;
52 
53   for (i = 0; i < 100; i++)
54   {
55     if((status & CAN_Mode_RM) != CAN_Mode_RM)
56     {
57       /*开所有中断 (总线错误中断不开)*/
58       CANx->IER |= (~(unsigned char)CAN_IR_BEI);
59       return 1;
60     }
61     /* 设置正常工作模式*/
62     CANx->MOD &= (~(unsigned char) CAN_Mode_RM);
63     /*延时*/
64     delay_us(10);
65     status = CANx->MOD;
66   }
67   printf("\r\nSetting SJA1000 into normal mode failed!\r\n");
68   return 0;
69 }
70 
set_start(CAN_TypeDef * CANx)71 unsigned char  set_start(CAN_TypeDef* CANx)
72 {
73   /*复位TX错误计数器*/
74   CANx->TXERR = 0;
75   /*复位RX错误计数器*/
76   CANx->RXERR = 0;
77   /*时钟分频寄存器: PeliCAN模式; CBP=1,中止输入比较器, RX0激活*/
78   CANx->CDR = 0xC0;
79 
80   return  set_normal_mode(CANx);
81 }
82 
CAN_Init(CAN_TypeDef * CANx,CAN_InitTypeDef * CAN_InitStruct)83 unsigned char CAN_Init(CAN_TypeDef* CANx, CAN_InitTypeDef* CAN_InitStruct)
84 {
85   unsigned char InitStatus = CAN_InitStatus_Failed;
86   unsigned long wait_ack = 0x00000000;
87   unsigned char status;
88 
89   status = CANx->MOD;
90   if( status == 0xFF)
91   {
92     printf("\n Probe can0 failed \r\n");
93     return CAN_InitStatus_Failed;
94   }
95 
96    /* 进入复位模式 */
97   InitStatus = set_reset_mode(CANx);
98 
99   if((CAN_InitStruct->CAN_Mode & CAN_Mode_SM) == CAN_Mode_SM)
100   {
101     /* 睡眠模式 1: 睡眠 0: 唤醒*/
102     CANx->MOD|= (unsigned char)CAN_Mode_SM;
103   }
104   else
105   {
106      CANx->MOD&=~ (unsigned char)CAN_Mode_SM;
107   }
108 
109  if((CAN_InitStruct->CAN_Mode & CAN_Mode_LOM) == CAN_Mode_LOM)
110   {
111     /*只听模式 1:只听  0:正常 */
112     CANx->MOD|= (unsigned char)CAN_Mode_LOM;
113   }
114   else
115   {
116      CANx->MOD&=~ (unsigned char)CAN_Mode_LOM;
117   }
118 
119   if((CAN_InitStruct->CAN_Mode & CAN_Mode_AFM) == CAN_Mode_AFM)
120   {
121     /*单滤波模式 1:单 0: 双*/
122     CANx->MOD |= (unsigned char)CAN_Mode_AFM;
123   }
124   else
125   {
126      CANx->MOD&=~ (unsigned char)CAN_Mode_AFM;
127   }
128 
129   if((CAN_InitStruct->CAN_Mode & CAN_Mode_STM) == CAN_Mode_STM)
130   {
131     /*自检测模式 1:自检测  0:正常  */
132     CANx->MOD |= (unsigned char)CAN_Mode_STM;
133   }
134   else
135   {
136      CANx->MOD&=~ (unsigned char)CAN_Mode_STM;
137   }
138 
139   /* 配置时钟频率 */
140   CANx->BTR0 = (( unsigned char )( unsigned char )CAN_InitStruct->CAN_Prescaler -1) | \
141                (unsigned char)CAN_InitStruct->CAN_SJW << 6;
142 
143   CANx->BTR1 = ((unsigned char)CAN_InitStruct->CAN_BS1) | \
144                ((unsigned char)CAN_InitStruct->CAN_BS2 << 4) | \
145                ((unsigned char)CAN_InitStruct->CAN_SJW<<7);
146 
147    /* 进入工作模式 */
148   set_start(CANx);
149 
150   /* 返回初始化结果 */
151   return InitStatus;
152 }
153 
CAN_FilterInit(CAN_TypeDef * CANx,CAN_FilterInitTypeDef * CAN_FilterInitStruct)154 void CAN_FilterInit(CAN_TypeDef* CANx,    CAN_FilterInitTypeDef * CAN_FilterInitStruct)
155 {
156     unsigned long rtr;
157     unsigned long fcase;
158     unsigned long ide;
159     unsigned long thisid, thisid1, thisid2;
160     unsigned long thismask, thismask1, thismask2;
161     unsigned long firstdata;
162     unsigned long datamask;
163     unsigned char CAN_FilterId0, CAN_FilterId1, CAN_FilterId2, CAN_FilterId3 ;
164     unsigned char CAN_FilterMaskId0, CAN_FilterMaskId1, CAN_FilterMaskId2, CAN_FilterMaskId3;
165 
166     thisid = CAN_FilterInitStruct->ID;
167     thismask = CAN_FilterInitStruct->IDMASK;
168     thisid1 = (CAN_FilterInitStruct->ID & 0xFFFF0000 )>>16;
169     thismask1 = (CAN_FilterInitStruct->IDMASK & 0xFFFF0000 )>>16;
170     thisid2 = (CAN_FilterInitStruct->ID & 0x0000FFFF );
171     thismask2 = ( CAN_FilterInitStruct->IDMASK& 0x0000FFFF  );
172     rtr = CAN_FilterInitStruct->RTR;
173     ide = CAN_FilterInitStruct->IDE;
174     firstdata = CAN_FilterInitStruct->First_Data;
175     datamask = CAN_FilterInitStruct->Data_Mask;
176     fcase = CAN_FilterInitStruct->MODE;
177 
178     if(ide == 0)//标准帧
179     {
180         if(fcase == 0)// 0- 双滤波器模式
181         {
182             CAN_FilterId0  = thisid1>>3;
183             CAN_FilterMaskId0 = thismask1>>3;
184             CAN_FilterId1  = thisid1<<5 | firstdata>>4| rtr<<4;
185             CAN_FilterMaskId1 = thismask1<<4 | datamask>>4 ;
186             CAN_FilterId2  = thisid2 >> 3;
187             CAN_FilterMaskId2 = thismask2 >>3;
188             CAN_FilterId3  = firstdata & 0x0F | thisid2 <<5 | rtr<<4;
189             CAN_FilterMaskId3 = datamask <<4  ;
190         }
191         else if(fcase == 1)// 1-单滤波器模式
192         {
193             CAN_FilterId0  = thisid>>3;
194             CAN_FilterMaskId0 = thismask>>3;
195             CAN_FilterId1  = thisid<<5 | rtr<<4;
196             CAN_FilterMaskId1 = thismask<<5  ;
197             CAN_FilterMaskId1 |= 0x0F ;
198             CAN_FilterId2  = 0x00;
199             CAN_FilterMaskId2 = 0xFF;
200             CAN_FilterId3  = 0x00;
201             CAN_FilterMaskId3 = 0xFF  ;
202         }
203     }
204     else if(ide == 1)//扩展帧
205     {
206         if(fcase == 0)// 0- 双滤波器模式
207         {
208             CAN_FilterId0  = thisid1>>8;
209             CAN_FilterMaskId0 = thismask1>>8;
210             CAN_FilterId1  = thisid1 ;
211             CAN_FilterMaskId1 = thismask1 ;
212             CAN_FilterId2  = thisid2>>8;
213             CAN_FilterMaskId2 = thismask2>>8;
214             CAN_FilterId3  = thisid2 ;
215             CAN_FilterMaskId3 = thismask2 ;
216         }
217         else if(fcase == 1)// 1-单滤波器模式
218         {
219             CAN_FilterId0  = thisid>>21;
220             CAN_FilterMaskId0 = thismask>>21;
221             CAN_FilterId1  = thisid>>13 ;
222             CAN_FilterMaskId1 = thismask>>13 ;
223             CAN_FilterId2  = thisid>>5;
224             CAN_FilterMaskId2 = thismask>>5;
225             CAN_FilterId3  = thisid<<3 | rtr<<2;
226             CAN_FilterMaskId3 = thismask<<3;
227             CAN_FilterMaskId3 |= 0x03;
228         }
229     }
230 
231     /* 进入复位模式 */
232     set_reset_mode(CANx);
233 
234     if(fcase == 1)// 1-单滤波器模式
235     {
236         /*单滤波模式 */
237         CANx->MOD |= (unsigned char)CAN_Mode_AFM;
238     }
239     else if(fcase == 1)// 0- 双滤波器模式
240     {
241         /*双滤波模式 */
242         CANx->MOD &=(~ (unsigned char) CAN_Mode_AFM);
243     }
244 
245     CANx->IDE_RTR_DLC = CAN_FilterId0;
246     CANx->ID[0] =  CAN_FilterId1;
247     CANx->ID[1] =  CAN_FilterId2;
248     CANx->ID[2] =  CAN_FilterId3;
249     CANx->ID[3] =  CAN_FilterMaskId0;
250     CANx->BUF[0] = CAN_FilterMaskId1;
251     CANx->BUF[1] = CAN_FilterMaskId2;
252     CANx->BUF[2] = CAN_FilterMaskId3;
253    /* 进入工作模式 */
254     set_start(CANx);
255 }
256 
CAN_SetBps(CAN_TypeDef * CANx,Ls1c_CanBPS_t Bps)257 unsigned char CAN_SetBps(CAN_TypeDef* CANx, Ls1c_CanBPS_t  Bps)
258 {
259     unsigned char InitStatus = CAN_InitStatus_Failed;
260     unsigned char  CAN_Prescaler, CAN_BS1, CAN_BS2, CAN_SJW;
261     CAN_SJW = CAN_SJW_1tq;
262    /* 进入复位模式 */
263   InitStatus = set_reset_mode(CANx);
264   if( InitStatus == CAN_InitStatus_Failed)
265   	return CAN_InitStatus_Failed;
266 
267     /* BaudRate= f(APB)/((1+BS1+BS2)(SJW*2*Prescaler))=126000000/[(1+7+2)*1*2*63]=100000=100K*/
268     /* BPS     PRE   BS1   BS2   最低40K
269        1M      9       4       2
270        800K    8       7       2
271        500K    9       11      2
272        250K    36      4       2
273        125K    36      11      2
274        100K    63      7       2
275        50K     63      16      3`
276        40K     63      16      8
277     */
278     switch (Bps)
279     {
280         case LS1C_CAN1MBaud:
281             CAN_Prescaler = 9;
282             CAN_BS1 = CAN_BS1_4tq;
283             CAN_BS2 = CAN_BS2_2tq;
284         break;
285         case LS1C_CAN800kBaud:
286             CAN_Prescaler = 8;
287             CAN_BS1 = CAN_BS1_7tq;
288             CAN_BS2 = CAN_BS2_2tq;
289         break;
290         case LS1C_CAN500kBaud:
291             CAN_Prescaler = 9;
292             CAN_BS1 = CAN_BS1_11tq;
293             CAN_BS2 = CAN_BS2_2tq;
294         break;
295         case LS1C_CAN250kBaud:
296             CAN_Prescaler = 36;
297             CAN_BS1 = CAN_BS1_4tq;
298             CAN_BS2 = CAN_BS2_2tq;
299         break;
300         case LS1C_CAN125kBaud:
301             CAN_Prescaler = 36;
302             CAN_BS1 = CAN_BS1_11tq;
303             CAN_BS2 = CAN_BS2_2tq;
304         break;
305         case LS1C_CAN100kBaud:
306             CAN_Prescaler = 63;
307             CAN_BS1 = CAN_BS1_7tq;
308             CAN_BS2 = CAN_BS2_2tq;
309         break;
310         case LS1C_CAN50kBaud:
311             CAN_Prescaler = 63;
312             CAN_BS1 = CAN_BS1_16tq;
313             CAN_BS2 = CAN_BS2_3tq;
314         break;
315         case LS1C_CAN40kBaud:
316             CAN_Prescaler = 63;
317             CAN_BS1 = CAN_BS1_16tq;
318             CAN_BS2 = CAN_BS2_8tq;
319         break;
320         default: //100K
321             CAN_Prescaler = 63;
322             CAN_BS1 = CAN_BS1_7tq;
323             CAN_BS2 = CAN_BS2_2tq;
324         break;
325     }
326   /* 配置时钟频率 */
327   CANx->BTR0 = (( unsigned char )CAN_Prescaler -1) | \
328                (unsigned char)CAN_SJW << 6;
329 
330   CANx->BTR1 = ((unsigned char)CAN_BS1) | \
331                ((unsigned char)CAN_BS2 << 4) | \
332                ((unsigned char)CAN_SJW<<7);
333 
334    /* 进入工作模式 */
335   set_start(CANx);
336   /* 返回初始化结果 */
337   return CAN_InitStatus_Failed;
338 }
339 
340 
CAN_SetMode(CAN_TypeDef * CANx,unsigned char mode)341 unsigned char CAN_SetMode(CAN_TypeDef* CANx, unsigned char  mode)
342 {
343   unsigned char InitStatus = CAN_InitStatus_Failed;
344   unsigned long wait_ack = 0x00000000;
345   CAN_InitTypeDef        CAN_InitStructure;
346 
347    /* 进入复位模式 */
348   InitStatus = set_reset_mode(CANx);
349   if( InitStatus == CAN_InitStatus_Failed)
350   	return CAN_InitStatus_Failed;
351 
352   switch( mode )
353   {
354     case 0://正常
355         CANx->MOD &= ~(unsigned char)CAN_Mode_STM;
356         CANx->MOD &= ~(unsigned char)CAN_Mode_LOM;
357       break;
358     case 1://只听
359         CANx->MOD &= ~(unsigned char)CAN_Mode_STM;
360         CANx->MOD |= (unsigned char)CAN_Mode_LOM;
361       break;
362     case 2://回环
363         CANx->MOD |= (unsigned char)CAN_Mode_STM;
364         CANx->MOD &= ~(unsigned char)CAN_Mode_LOM;
365       break;
366     case 3://只听回环
367         CANx->MOD |= (unsigned char)CAN_Mode_STM;
368         CANx->MOD |= (unsigned char)CAN_Mode_LOM;
369       break;
370   }
371    /* 进入工作模式 */
372   set_start(CANx);
373 
374   /* 返回初始化结果 */
375   return CAN_InitStatus_Failed;
376  }
377 
CAN_Transmit(CAN_TypeDef * CANx,CanTxMsg * TxMessage)378 unsigned char  CAN_Transmit(CAN_TypeDef* CANx, CanTxMsg* TxMessage)
379 {
380     int i;
381     if (TxMessage->IDE == CAN_Id_Extended)
382     {
383         CANx->ID[0]= TxMessage ->ExtId>> 21;
384         CANx->ID[1]= TxMessage ->ExtId>> 13;
385         CANx->ID[2]= TxMessage ->ExtId>> 5;
386         CANx->ID[3]= TxMessage ->ExtId<<3;
387         CANx->IDE_RTR_DLC= (TxMessage ->IDE & 0x01) << 7 |\
388             (TxMessage ->RTR & 0x01) << 6 |\
389             (TxMessage ->DLC & 0x0F);
390         for( i=0;i<TxMessage ->DLC; i++)
391         {
392            CANx->BUF[i]= TxMessage->Data[i];
393         }
394     }
395     else if (TxMessage->IDE ==CAN_Id_Standard)
396     {
397         CANx->ID[0]= TxMessage ->StdId>> 3;
398         CANx->ID[1]= TxMessage ->StdId<< 5;
399         CANx->IDE_RTR_DLC= (TxMessage ->IDE & 0x01) << 7 |\
400             (TxMessage ->RTR & 0x01) << 6 |\
401             (TxMessage ->DLC & 0x0F);
402         CANx->ID[2]= TxMessage ->Data[0];
403         CANx->ID[3]= TxMessage ->Data[1];
404         for( i=0;i<TxMessage ->DLC-2; i++)
405         {
406            CANx->BUF[i]= TxMessage->Data[i+2];
407         }
408     }
409     CANx->CMR = CAN_CMR_TR ;
410 }
411 
CAN_Receive(CAN_TypeDef * CANx,CanRxMsg * RxMessage)412 void CAN_Receive(CAN_TypeDef* CANx,  CanRxMsg* RxMessage)
413 {
414   /* 获取 IDE */
415   RxMessage->IDE = (CANx->IDE_RTR_DLC  & 0x80)>>7;
416   /* 获取 RTR */
417   RxMessage->RTR = (CANx->IDE_RTR_DLC  & 0x40)>>4;
418   /* 获取 DLC */
419   RxMessage->DLC= (CANx->IDE_RTR_DLC  & 0x0F);
420   if (RxMessage->IDE == CAN_Id_Standard)
421   {
422     RxMessage->StdId = CANx->ID[0]<<3 |CANx->ID[1]>>5 ;
423     /* 获取数据 */
424     RxMessage->Data[0] = (unsigned char)CANx->ID[2];
425     RxMessage->Data[1] = (unsigned char)CANx->ID[3];
426     RxMessage->Data[2] = (unsigned char)CANx->BUF[0];
427     RxMessage->Data[3] = (unsigned char)CANx->BUF[1];
428     RxMessage->Data[4] = (unsigned char)CANx->BUF[2];
429     RxMessage->Data[5] = (unsigned char)CANx->BUF[3];
430     RxMessage->Data[6] = (unsigned char)CANx->BUF[4];
431     RxMessage->Data[7] = (unsigned char)CANx->BUF[5];
432   }
433   else  if (RxMessage->IDE == CAN_Id_Extended)
434   {
435     RxMessage->ExtId= CANx->ID[0]<<21 |CANx->ID[1]<<13|CANx->ID[2]<<5|CANx->ID[3]>>3 ;
436     /* 获取数据 */
437     RxMessage->Data[0] = (unsigned char)CANx->BUF[0];
438     RxMessage->Data[1] = (unsigned char)CANx->BUF[1];
439     RxMessage->Data[2] = (unsigned char)CANx->BUF[2];
440     RxMessage->Data[3] = (unsigned char)CANx->BUF[3];
441     RxMessage->Data[4] = (unsigned char)CANx->BUF[4];
442     RxMessage->Data[5] = (unsigned char)CANx->BUF[5];
443     RxMessage->Data[6] = (unsigned char)CANx->BUF[6];
444     RxMessage->Data[7] = (unsigned char)CANx->BUF[7];
445   }
446 }
447 
448