123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447 |
- /*
- * Copyright (c) 2006-2018, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2018-01-06 sundm75 first version
- */
- #include "ls1c.h"
- #include "ls1c_public.h"
- #include "ls1c_can.h"
- #include "ls1c_delay.h"
- unsigned char set_reset_mode(CAN_TypeDef* CANx)
- {
- unsigned char status;
- int i;
- /*检查复位标志*/
- status = CANx->MOD;
- /* 关闭中断 */
- CANx->IER = 0x00;
-
- for (i = 0; i < 100; i++)
- {
- if((status & CAN_Mode_RM) == CAN_Mode_RM)
- return 1;
-
- /* 设置复位*/
- CANx->MOD |= ((unsigned char)CAN_Mode_RM);
-
- /*延时*/
- delay_us(10);
- /*检查复位标志*/
- status = CANx->MOD;
- }
- printf("\r\nSetting SJA1000 into reset mode failed!\r\n");
- return 0;
- }
- static unsigned char set_normal_mode(CAN_TypeDef* CANx)
- {
- unsigned char status;
- int i;
- /*检查复位标志*/
- status = CANx->MOD;
-
- for (i = 0; i < 100; i++)
- {
- if((status & CAN_Mode_RM) != CAN_Mode_RM)
- {
- /*开所有中断 (总线错误中断不开)*/
- CANx->IER |= (~(unsigned char)CAN_IR_BEI);
- return 1;
- }
- /* 设置正常工作模式*/
- CANx->MOD &= (~(unsigned char) CAN_Mode_RM);
- /*延时*/
- delay_us(10);
- status = CANx->MOD;
- }
- printf("\r\nSetting SJA1000 into normal mode failed!\r\n");
- return 0;
- }
- unsigned char set_start(CAN_TypeDef* CANx)
- {
- /*复位TX错误计数器*/
- CANx->TXERR = 0;
- /*复位RX错误计数器*/
- CANx->RXERR = 0;
- /*时钟分频寄存器: PeliCAN模式; CBP=1,中止输入比较器, RX0激活*/
- CANx->CDR = 0xC0;
-
- return set_normal_mode(CANx);
- }
- unsigned char CAN_Init(CAN_TypeDef* CANx, CAN_InitTypeDef* CAN_InitStruct)
- {
- unsigned char InitStatus = CAN_InitStatus_Failed;
- unsigned long wait_ack = 0x00000000;
- unsigned char status;
- status = CANx->MOD;
- if( status == 0xFF)
- {
- printf("\n Probe can0 failed \r\n");
- return CAN_InitStatus_Failed;
- }
- /* 进入复位模式 */
- InitStatus = set_reset_mode(CANx);
-
- if((CAN_InitStruct->CAN_Mode & CAN_Mode_SM) == CAN_Mode_SM)
- {
- /* 睡眠模式 1: 睡眠 0: 唤醒*/
- CANx->MOD|= (unsigned char)CAN_Mode_SM;
- }
- else
- {
- CANx->MOD&=~ (unsigned char)CAN_Mode_SM;
- }
- if((CAN_InitStruct->CAN_Mode & CAN_Mode_LOM) == CAN_Mode_LOM)
- {
- /*只听模式 1:只听 0:正常 */
- CANx->MOD|= (unsigned char)CAN_Mode_LOM;
- }
- else
- {
- CANx->MOD&=~ (unsigned char)CAN_Mode_LOM;
- }
- if((CAN_InitStruct->CAN_Mode & CAN_Mode_AFM) == CAN_Mode_AFM)
- {
- /*单滤波模式 1:单 0: 双*/
- CANx->MOD |= (unsigned char)CAN_Mode_AFM;
- }
- else
- {
- CANx->MOD&=~ (unsigned char)CAN_Mode_AFM;
- }
- if((CAN_InitStruct->CAN_Mode & CAN_Mode_STM) == CAN_Mode_STM)
- {
- /*自检测模式 1:自检测 0:正常 */
- CANx->MOD |= (unsigned char)CAN_Mode_STM;
- }
- else
- {
- CANx->MOD&=~ (unsigned char)CAN_Mode_STM;
- }
-
- /* 配置时钟频率 */
- CANx->BTR0 = (( unsigned char )( unsigned char )CAN_InitStruct->CAN_Prescaler -1) | \
- (unsigned char)CAN_InitStruct->CAN_SJW << 6;
-
- CANx->BTR1 = ((unsigned char)CAN_InitStruct->CAN_BS1) | \
- ((unsigned char)CAN_InitStruct->CAN_BS2 << 4) | \
- ((unsigned char)CAN_InitStruct->CAN_SJW<<7);
- /* 进入工作模式 */
- set_start(CANx);
-
- /* 返回初始化结果 */
- return InitStatus;
- }
- void CAN_FilterInit(CAN_TypeDef* CANx, CAN_FilterInitTypeDef * CAN_FilterInitStruct)
- {
- unsigned long rtr;
- unsigned long fcase;
- unsigned long ide;
- unsigned long thisid, thisid1, thisid2;
- unsigned long thismask, thismask1, thismask2;
- unsigned long firstdata;
- unsigned long datamask;
- unsigned char CAN_FilterId0, CAN_FilterId1, CAN_FilterId2, CAN_FilterId3 ;
- unsigned char CAN_FilterMaskId0, CAN_FilterMaskId1, CAN_FilterMaskId2, CAN_FilterMaskId3;
- thisid = CAN_FilterInitStruct->ID;
- thismask = CAN_FilterInitStruct->IDMASK;
- thisid1 = (CAN_FilterInitStruct->ID & 0xFFFF0000 )>>16;
- thismask1 = (CAN_FilterInitStruct->IDMASK & 0xFFFF0000 )>>16;
- thisid2 = (CAN_FilterInitStruct->ID & 0x0000FFFF );
- thismask2 = ( CAN_FilterInitStruct->IDMASK& 0x0000FFFF );
- rtr = CAN_FilterInitStruct->RTR;
- ide = CAN_FilterInitStruct->IDE;
- firstdata = CAN_FilterInitStruct->First_Data;
- datamask = CAN_FilterInitStruct->Data_Mask;
- fcase = CAN_FilterInitStruct->MODE;
- if(ide == 0)//标准帧
- {
- if(fcase == 0)// 0- 双滤波器模式
- {
- CAN_FilterId0 = thisid1>>3;
- CAN_FilterMaskId0 = thismask1>>3;
- CAN_FilterId1 = thisid1<<5 | firstdata>>4| rtr<<4;
- CAN_FilterMaskId1 = thismask1<<4 | datamask>>4 ;
- CAN_FilterId2 = thisid2 >> 3;
- CAN_FilterMaskId2 = thismask2 >>3;
- CAN_FilterId3 = firstdata & 0x0F | thisid2 <<5 | rtr<<4;
- CAN_FilterMaskId3 = datamask <<4 ;
- }
- else if(fcase == 1)// 1-单滤波器模式
- {
- CAN_FilterId0 = thisid>>3;
- CAN_FilterMaskId0 = thismask>>3;
- CAN_FilterId1 = thisid<<5 | rtr<<4;
- CAN_FilterMaskId1 = thismask<<5 ;
- CAN_FilterMaskId1 |= 0x0F ;
- CAN_FilterId2 = 0x00;
- CAN_FilterMaskId2 = 0xFF;
- CAN_FilterId3 = 0x00;
- CAN_FilterMaskId3 = 0xFF ;
- }
- }
- else if(ide == 1)//扩展帧
- {
- if(fcase == 0)// 0- 双滤波器模式
- {
- CAN_FilterId0 = thisid1>>8;
- CAN_FilterMaskId0 = thismask1>>8;
- CAN_FilterId1 = thisid1 ;
- CAN_FilterMaskId1 = thismask1 ;
- CAN_FilterId2 = thisid2>>8;
- CAN_FilterMaskId2 = thismask2>>8;
- CAN_FilterId3 = thisid2 ;
- CAN_FilterMaskId3 = thismask2 ;
- }
- else if(fcase == 1)// 1-单滤波器模式
- {
- CAN_FilterId0 = thisid>>21;
- CAN_FilterMaskId0 = thismask>>21;
- CAN_FilterId1 = thisid>>13 ;
- CAN_FilterMaskId1 = thismask>>13 ;
- CAN_FilterId2 = thisid>>5;
- CAN_FilterMaskId2 = thismask>>5;
- CAN_FilterId3 = thisid<<3 | rtr<<2;
- CAN_FilterMaskId3 = thismask<<3;
- CAN_FilterMaskId3 |= 0x03;
- }
- }
- /* 进入复位模式 */
- set_reset_mode(CANx);
-
- if(fcase == 1)// 1-单滤波器模式
- {
- /*单滤波模式 */
- CANx->MOD |= (unsigned char)CAN_Mode_AFM;
- }
- else if(fcase == 1)// 0- 双滤波器模式
- {
- /*双滤波模式 */
- CANx->MOD &=(~ (unsigned char) CAN_Mode_AFM);
- }
- CANx->IDE_RTR_DLC = CAN_FilterId0;
- CANx->ID[0] = CAN_FilterId1;
- CANx->ID[1] = CAN_FilterId2;
- CANx->ID[2] = CAN_FilterId3;
- CANx->ID[3] = CAN_FilterMaskId0;
- CANx->BUF[0] = CAN_FilterMaskId1;
- CANx->BUF[1] = CAN_FilterMaskId2;
- CANx->BUF[2] = CAN_FilterMaskId3;
- /* 进入工作模式 */
- set_start(CANx);
- }
- unsigned char CAN_SetBps(CAN_TypeDef* CANx, Ls1c_CanBPS_t Bps)
- {
- unsigned char InitStatus = CAN_InitStatus_Failed;
- unsigned char CAN_Prescaler, CAN_BS1, CAN_BS2, CAN_SJW;
- CAN_SJW = CAN_SJW_1tq;
- /* 进入复位模式 */
- InitStatus = set_reset_mode(CANx);
- if( InitStatus == CAN_InitStatus_Failed)
- return CAN_InitStatus_Failed;
- /* BaudRate= f(APB)/((1+BS1+BS2)(SJW*2*Prescaler))=126000000/[(1+7+2)*1*2*63]=100000=100K*/
- /* BPS PRE BS1 BS2 最低40K
- 1M 9 4 2
- 800K 8 7 2
- 500K 9 11 2
- 250K 36 4 2
- 125K 36 11 2
- 100K 63 7 2
- 50K 63 16 3`
- 40K 63 16 8
- */
- switch (Bps)
- {
- case LS1C_CAN1MBaud:
- CAN_Prescaler = 9;
- CAN_BS1 = CAN_BS1_4tq;
- CAN_BS2 = CAN_BS2_2tq;
- break;
- case LS1C_CAN800kBaud:
- CAN_Prescaler = 8;
- CAN_BS1 = CAN_BS1_7tq;
- CAN_BS2 = CAN_BS2_2tq;
- break;
- case LS1C_CAN500kBaud:
- CAN_Prescaler = 9;
- CAN_BS1 = CAN_BS1_11tq;
- CAN_BS2 = CAN_BS2_2tq;
- break;
- case LS1C_CAN250kBaud:
- CAN_Prescaler = 36;
- CAN_BS1 = CAN_BS1_4tq;
- CAN_BS2 = CAN_BS2_2tq;
- break;
- case LS1C_CAN125kBaud:
- CAN_Prescaler = 36;
- CAN_BS1 = CAN_BS1_11tq;
- CAN_BS2 = CAN_BS2_2tq;
- break;
- case LS1C_CAN100kBaud:
- CAN_Prescaler = 63;
- CAN_BS1 = CAN_BS1_7tq;
- CAN_BS2 = CAN_BS2_2tq;
- break;
- case LS1C_CAN50kBaud:
- CAN_Prescaler = 63;
- CAN_BS1 = CAN_BS1_16tq;
- CAN_BS2 = CAN_BS2_3tq;
- break;
- case LS1C_CAN40kBaud:
- CAN_Prescaler = 63;
- CAN_BS1 = CAN_BS1_16tq;
- CAN_BS2 = CAN_BS2_8tq;
- break;
- default: //100K
- CAN_Prescaler = 63;
- CAN_BS1 = CAN_BS1_7tq;
- CAN_BS2 = CAN_BS2_2tq;
- break;
- }
- /* 配置时钟频率 */
- CANx->BTR0 = (( unsigned char )CAN_Prescaler -1) | \
- (unsigned char)CAN_SJW << 6;
-
- CANx->BTR1 = ((unsigned char)CAN_BS1) | \
- ((unsigned char)CAN_BS2 << 4) | \
- ((unsigned char)CAN_SJW<<7);
- /* 进入工作模式 */
- set_start(CANx);
- /* 返回初始化结果 */
- return CAN_InitStatus_Failed;
- }
- unsigned char CAN_SetMode(CAN_TypeDef* CANx, unsigned char mode)
- {
- unsigned char InitStatus = CAN_InitStatus_Failed;
- unsigned long wait_ack = 0x00000000;
- CAN_InitTypeDef CAN_InitStructure;
- /* 进入复位模式 */
- InitStatus = set_reset_mode(CANx);
- if( InitStatus == CAN_InitStatus_Failed)
- return CAN_InitStatus_Failed;
- switch( mode )
- {
- case 0://正常
- CANx->MOD &= ~(unsigned char)CAN_Mode_STM;
- CANx->MOD &= ~(unsigned char)CAN_Mode_LOM;
- break;
- case 1://只听
- CANx->MOD &= ~(unsigned char)CAN_Mode_STM;
- CANx->MOD |= (unsigned char)CAN_Mode_LOM;
- break;
- case 2://回环
- CANx->MOD |= (unsigned char)CAN_Mode_STM;
- CANx->MOD &= ~(unsigned char)CAN_Mode_LOM;
- break;
- case 3://只听回环
- CANx->MOD |= (unsigned char)CAN_Mode_STM;
- CANx->MOD |= (unsigned char)CAN_Mode_LOM;
- break;
- }
- /* 进入工作模式 */
- set_start(CANx);
-
- /* 返回初始化结果 */
- return CAN_InitStatus_Failed;
- }
- unsigned char CAN_Transmit(CAN_TypeDef* CANx, CanTxMsg* TxMessage)
- {
- int i;
- if (TxMessage->IDE == CAN_Id_Extended)
- {
- CANx->ID[0]= TxMessage ->ExtId>> 21;
- CANx->ID[1]= TxMessage ->ExtId>> 13;
- CANx->ID[2]= TxMessage ->ExtId>> 5;
- CANx->ID[3]= TxMessage ->ExtId<<3;
- CANx->IDE_RTR_DLC= (TxMessage ->IDE & 0x01) << 7 |\
- (TxMessage ->RTR & 0x01) << 6 |\
- (TxMessage ->DLC & 0x0F);
- for( i=0;i<TxMessage ->DLC; i++)
- {
- CANx->BUF[i]= TxMessage->Data[i];
- }
- }
- else if (TxMessage->IDE ==CAN_Id_Standard)
- {
- CANx->ID[0]= TxMessage ->StdId>> 3;
- CANx->ID[1]= TxMessage ->StdId<< 5;
- CANx->IDE_RTR_DLC= (TxMessage ->IDE & 0x01) << 7 |\
- (TxMessage ->RTR & 0x01) << 6 |\
- (TxMessage ->DLC & 0x0F);
- CANx->ID[2]= TxMessage ->Data[0];
- CANx->ID[3]= TxMessage ->Data[1];
- for( i=0;i<TxMessage ->DLC-2; i++)
- {
- CANx->BUF[i]= TxMessage->Data[i+2];
- }
- }
- CANx->CMR = CAN_CMR_TR ;
- }
- void CAN_Receive(CAN_TypeDef* CANx, CanRxMsg* RxMessage)
- {
- /* 获取 IDE */
- RxMessage->IDE = (CANx->IDE_RTR_DLC & 0x80)>>7;
- /* 获取 RTR */
- RxMessage->RTR = (CANx->IDE_RTR_DLC & 0x40)>>4;
- /* 获取 DLC */
- RxMessage->DLC= (CANx->IDE_RTR_DLC & 0x0F);
- if (RxMessage->IDE == CAN_Id_Standard)
- {
- RxMessage->StdId = CANx->ID[0]<<3 |CANx->ID[1]>>5 ;
- /* 获取数据 */
- RxMessage->Data[0] = (unsigned char)CANx->ID[2];
- RxMessage->Data[1] = (unsigned char)CANx->ID[3];
- RxMessage->Data[2] = (unsigned char)CANx->BUF[0];
- RxMessage->Data[3] = (unsigned char)CANx->BUF[1];
- RxMessage->Data[4] = (unsigned char)CANx->BUF[2];
- RxMessage->Data[5] = (unsigned char)CANx->BUF[3];
- RxMessage->Data[6] = (unsigned char)CANx->BUF[4];
- RxMessage->Data[7] = (unsigned char)CANx->BUF[5];
- }
- else if (RxMessage->IDE == CAN_Id_Extended)
- {
- RxMessage->ExtId= CANx->ID[0]<<21 |CANx->ID[1]<<13|CANx->ID[2]<<5|CANx->ID[3]>>3 ;
- /* 获取数据 */
- RxMessage->Data[0] = (unsigned char)CANx->BUF[0];
- RxMessage->Data[1] = (unsigned char)CANx->BUF[1];
- RxMessage->Data[2] = (unsigned char)CANx->BUF[2];
- RxMessage->Data[3] = (unsigned char)CANx->BUF[3];
- RxMessage->Data[4] = (unsigned char)CANx->BUF[4];
- RxMessage->Data[5] = (unsigned char)CANx->BUF[5];
- RxMessage->Data[6] = (unsigned char)CANx->BUF[6];
- RxMessage->Data[7] = (unsigned char)CANx->BUF[7];
- }
- }
|