can使用还是比较广泛的,之前有网友在龙芯1b和龙芯1c上已经测试过了在裸机编程中使用CAN接口,这里把他们分享的程序贴上来,供大家参考。
龙芯1b上的测试程序在https://gitee.com/caogos/OpenLoongsonLib1b
龙芯1c上的测试程序在https://gitee.com/caogos/OpenLoongsonLib1c
据说,淘宝上的CAN模块TJA1050可以用。
这里,把龙芯1c的测试程序和封装的接口函数都贴上来
源码
test_can.c
/* * File : test_can.c 测试硬件can驱动 1.test_cansend() 初始化CAN口(100K)后,以速率100K, 发送标准数据帧(1-8 共8个数据)和扩展数据帧(1-8 共8个数据) 2. candump() 打印出当前CAN寄存器值 3. 当收到数据,打印出来。 */ #include "../lib/ls1c_public.h" #include "../lib/ls1c_regs.h" #include "../lib/ls1c_clock.h" #include "../lib/ls1c_can.h" #include "../lib/ls1c_pin.h" #include "../lib/ls1c_irq.h" CanRxMsg RxMessage; CanTxMsg TxMessage; void candump(void) { CAN_TypeDef* CANx; unsigned char temp; CANx = CAN0; temp = CANx->MOD; printf("\r\ncan0->MOD= 0x%02x \r\n",temp); temp = CANx->CMR; printf("\ncan0->CMR = 0x%02x \r\n",temp); temp = CANx->SR; printf("\ncan0->SR = 0x%02x \r\n",temp); temp = CANx->IR; printf("\ncan0->IR = 0x%02x \r\n",temp); temp = CANx->IER; printf("\ncan0->IER = 0x%02x \r\n",temp); temp = CANx->BTR0; printf("\ncan0->BTR0 = 0x%02x \r\n",temp); temp = CANx->BTR1; printf("\ncan0->BTR1 = 0x%02x \r\n",temp); temp = CANx->CDR; printf("\ncan0->CDR = 0x%02x \r\n",temp); temp = CANx->RMCR; printf("\ncan0->RMCR = 0x%02x \r\n",temp); printf("\r\n验收代码:"); temp = CANx->IDE_RTR_DLC; printf(" 0x%02x ",temp); temp = CANx->ID[0]; printf(" 0x%02x ",temp); temp = CANx->ID[1]; printf(" 0x%02x ",temp); temp = CANx->ID[2]; printf(" 0x%02x ",temp); printf("\r\n验收屏蔽:"); temp = CANx->ID[3]; printf(" 0x%02x ",temp); temp = CANx->BUF[0]; printf(" 0x%02x ",temp); temp = CANx->BUF[1]; printf(" 0x%02x ",temp); temp = CANx->BUF[2]; printf(" 0x%02x ",temp); } void ls1c_can0_irqhandler(int irq, void *param) { CAN_TypeDef* CANx; int i; unsigned char status; CANx = CAN0; /*读寄存器清除中断*/ status = CANx->IR; printf("\r\ncan0 int happened!\r\n"); /*接收中断*/ if (( status & CAN_IR_RI) == CAN_IR_RI) { /*清除RI 中断*/ CAN_Receive(CANx, &RxMessage); CANx->CMR |= CAN_CMR_RRB; CANx->CMR |= CAN_CMR_CDO; printf("\r\ncan0 receive:\r\n"); printf(" IDE=%d RTR = %d DLC=%d ",RxMessage.IDE, RxMessage.RTR ,RxMessage.DLC); if(RxMessage.IDE == CAN_Id_Standard) { printf("\r\n Standard ID= %02X ",RxMessage.StdId); } else if(RxMessage.IDE == CAN_Id_Extended) { printf("\r\n Extended ID= %02X ",RxMessage.ExtId); } if(RxMessage.RTR== CAN_RTR_DATA) { printf("\r\ndata= "); for(i=0;i<RxMessage.DLC;i++) { printf("0x%02X ",RxMessage.Data[i]); } } else if(RxMessage.IDE == CAN_RTR_Remote) { printf("\r\nCAN_RTR_Remote no data!"); } printf("\r\n"); } /*发送中断*/ else if (( status & CAN_IR_TI) == CAN_IR_TI) { printf("\r\ncan0 send success! \r\n"); } } void ls1c_can1_irqhandler(int irq, void *param) { CAN_TypeDef* CANx; int i; unsigned char status; CANx = (CAN_TypeDef* )LS1C_REG_BASE_CAN1; /*读寄存器清除中断*/ status = CANx->IR; printf("\r\ncan1 int happened!\r\n"); /*接收中断*/ if (( status & CAN_IR_RI) == CAN_IR_RI) { /*清除RI 中断*/ CAN_Receive(CANx, &RxMessage); CANx->CMR |= CAN_CMR_RRB; CANx->CMR |= CAN_CMR_CDO; printf("\r\ncan1 receive:\r\n"); printf(" IDE=%d RTR = %d DLC=%d ",RxMessage.IDE, RxMessage.RTR ,RxMessage.DLC); if(RxMessage.IDE == CAN_Id_Standard) { printf("\r\n Standard ID= %02X ",RxMessage.StdId); } else if(RxMessage.IDE == CAN_Id_Extended) { printf("\r\n Extended ID= %02X ",RxMessage.ExtId); } if(RxMessage.RTR== CAN_RTR_DATA) { printf("\r\ndata= "); for(i=0;i<RxMessage.DLC;i++) { printf("0x%02X ",RxMessage.Data[i]); } } else if(RxMessage.IDE == CAN_RTR_Remote) { printf("\r\nCAN_RTR_Remote no data!"); } printf("\r\n"); } /*发送中断*/ else if (( status & CAN_IR_TI) == CAN_IR_TI) { printf("\r\ncan1 send success! \r\n"); } } void Can_Config(CAN_TypeDef* CANx, Ls1c_CanBPS_t bps) { unsigned char initresult; pin_set_purpose(54, PIN_PURPOSE_OTHER); pin_set_purpose(55, PIN_PURPOSE_OTHER); pin_set_remap(54, PIN_REMAP_THIRD); pin_set_remap(55, PIN_REMAP_THIRD); CAN_InitTypeDef CAN_InitStructure; CAN_InitStructure.CAN_Mode = CAN_Mode_STM; CAN_InitStructure.CAN_SJW = CAN_SJW_1tq; /* 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 CAN1MBaud: CAN_InitStructure.CAN_Prescaler = 9; CAN_InitStructure.CAN_BS1 = CAN_BS1_4tq; CAN_InitStructure.CAN_BS2 = CAN_BS2_2tq; break; case CAN800kBaud: CAN_InitStructure.CAN_Prescaler = 8; CAN_InitStructure.CAN_BS1 = CAN_BS1_7tq; CAN_InitStructure.CAN_BS2 = CAN_BS2_2tq; break; case CAN500kBaud: CAN_InitStructure.CAN_Prescaler = 9; CAN_InitStructure.CAN_BS1 = CAN_BS1_11tq; CAN_InitStructure.CAN_BS2 = CAN_BS2_2tq; break; case CAN250kBaud: CAN_InitStructure.CAN_Prescaler = 36; CAN_InitStructure.CAN_BS1 = CAN_BS1_4tq; CAN_InitStructure.CAN_BS2 = CAN_BS2_2tq; break; case CAN125kBaud: CAN_InitStructure.CAN_Prescaler = 36; CAN_InitStructure.CAN_BS1 = CAN_BS1_11tq; CAN_InitStructure.CAN_BS2 = CAN_BS2_2tq; break; case CAN100kBaud: CAN_InitStructure.CAN_Prescaler = 63; CAN_InitStructure.CAN_BS1 = CAN_BS1_7tq; CAN_InitStructure.CAN_BS2 = CAN_BS2_2tq; break; case CAN50kBaud: CAN_InitStructure.CAN_Prescaler = 63; CAN_InitStructure.CAN_BS1 = CAN_BS1_16tq; CAN_InitStructure.CAN_BS2 = CAN_BS2_3tq; break; case CAN40kBaud: CAN_InitStructure.CAN_Prescaler = 63; CAN_InitStructure.CAN_BS1 = CAN_BS1_16tq; CAN_InitStructure.CAN_BS2 = CAN_BS2_8tq; break; default: //100K CAN_InitStructure.CAN_Prescaler = 63; CAN_InitStructure.CAN_BS1 = CAN_BS1_7tq; CAN_InitStructure.CAN_BS2 = CAN_BS2_2tq; break; } initresult = CAN_Init(CANx, &CAN_InitStructure);// 配置成100K /*无验收屏蔽*/ CAN_FilterInitTypeDef CAN_FilterInitStructure; CAN_FilterInitStructure.CAN_FilterId0 = 0x00; CAN_FilterInitStructure.CAN_FilterMaskId0 = 0xFF; CAN_FilterInitStructure.CAN_FilterId1 = 0x00; CAN_FilterInitStructure.CAN_FilterMaskId1 = 0xFF; CAN_FilterInitStructure.CAN_FilterId2 = 0x00; CAN_FilterInitStructure.CAN_FilterMaskId2 = 0xFF; CAN_FilterInitStructure.CAN_FilterId3 = 0x00; CAN_FilterInitStructure.CAN_FilterMaskId3 = 0xFF; CAN_FilterInit(CANx, &CAN_FilterInitStructure); if( (CAN_TypeDef* )LS1C_REG_BASE_CAN0 == CANx) { /* 初始化CAN0接收中断*/ irq_install(LS1C_CAN0_IRQ, ls1c_can0_irqhandler, NULL); irq_enable(LS1C_CAN0_IRQ); } else if( (CAN_TypeDef* )LS1C_REG_BASE_CAN1 == CANx) { /* 初始化CAN1接收中断*/ irq_install(LS1C_CAN1_IRQ, ls1c_can1_irqhandler, NULL); irq_enable(LS1C_CAN1_IRQ); } } void test_cansend(void) { unsigned char temp; Can_Config(CAN0, CAN100kBaud); int i; TxMessage.StdId = 1; TxMessage.ExtId = 1; TxMessage.RTR = CAN_RTR_DATA; TxMessage.IDE = CAN_Id_Standard; TxMessage.DLC = 8; for( i=0; i<8;i++) { TxMessage.Data[i] = i+1; printf("%02x ", TxMessage.Data[i]); } CAN_Transmit(CAN0, &TxMessage); TxMessage.StdId = 1; TxMessage.ExtId = 2; TxMessage.RTR = CAN_RTR_DATA; TxMessage.IDE = CAN_Id_Extended; TxMessage.DLC = 8; for( i=0; i<8;i++) { TxMessage.Data[i] = i+1; printf("%02x ", TxMessage.Data[i]); } CAN_Transmit(CAN0, &TxMessage); }
Ls1c_can.c
/* * File : ls1c_can.c * This file is part of RT-Thread RTOS * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Change Logs: * Date Author Notes * 2018-01-06 sundm75 first version */ #include "ls1c_delay.h" #include "ls1c_public.h" #include "ls1c_can.h" static 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; } static 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 if((CAN_InitStruct->CAN_Mode & CAN_Mode_LOM) == CAN_Mode_LOM) { /*只听模式 1:只听 0:正常 */ CANx->MOD|= (unsigned char)CAN_Mode_LOM; } else if((CAN_InitStruct->CAN_Mode & CAN_Mode_AFM) == CAN_Mode_AFM) { /*单滤波模式 1:单 0: 双*/ CANx->MOD |= (unsigned char)CAN_Mode_AFM; } else if((CAN_InitStruct->CAN_Mode & CAN_Mode_STM) == CAN_Mode_STM) { /*自检测模式 1:自检测 0:正常 */ 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) { /* 进入复位模式 */ set_reset_mode(CANx); CANx->IDE_RTR_DLC = CAN_FilterInitStruct->CAN_FilterId0; CANx->ID[0] = CAN_FilterInitStruct->CAN_FilterId1; CANx->ID[1] = CAN_FilterInitStruct->CAN_FilterId2; CANx->ID[2] = CAN_FilterInitStruct->CAN_FilterId3; CANx->ID[3] = CAN_FilterInitStruct->CAN_FilterMaskId0; CANx->BUF[0]= CAN_FilterInitStruct->CAN_FilterMaskId1; CANx->BUF[1]= CAN_FilterInitStruct->CAN_FilterMaskId2; CANx->BUF[2]= CAN_FilterInitStruct->CAN_FilterMaskId3; /* 进入工作模式 */ set_start(CANx); } 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]; } }
Ls1c_can.h
/* * File : ls1c_can.h * This file is part of RT-Thread RTOS * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Change Logs: (Pelican Mode) * Date Author Notes * 2018-01-06 sundm75 first version */ #ifndef __OPENLOONGSON_CAN_H #define __OPENLOONGSON_CAN_H #define CAN0 ( (CAN_TypeDef* )LS1C_REG_BASE_CAN0) #define CAN1 ( (CAN_TypeDef* )LS1C_REG_BASE_CAN1) #define CAN_InitStatus_Failed ((unsigned char)0x00) /*!< CAN initialization failed */ #define CAN_InitStatus_Success ((unsigned char)0x01) /*!< CAN initialization OK */ /* 非应答溢出时间次数 */ #define INAK_TIMEOUT ((unsigned long)0x00000FFF) #define CAN_SJW_1tq ((unsigned char)0x00) /*!< 1 time quantum */ #define CAN_SJW_2tq ((unsigned char)0x01) /*!< 2 time quantum */ #define CAN_SJW_3tq ((unsigned char)0x02) /*!< 3 time quantum */ #define CAN_SJW_4tq ((unsigned char)0x03) /*!< 4 time quantum */ #define CAN_BS1_1tq ((unsigned char)0x00) /*!< 1 time quantum */ #define CAN_BS1_2tq ((unsigned char)0x01) /*!< 2 time quantum */ #define CAN_BS1_3tq ((unsigned char)0x02) /*!< 3 time quantum */ #define CAN_BS1_4tq ((unsigned char)0x03) /*!< 4 time quantum */ #define CAN_BS1_5tq ((unsigned char)0x04) /*!< 5 time quantum */ #define CAN_BS1_6tq ((unsigned char)0x05) /*!< 6 time quantum */ #define CAN_BS1_7tq ((unsigned char)0x06) /*!< 7 time quantum */ #define CAN_BS1_8tq ((unsigned char)0x07) /*!< 8 time quantum */ #define CAN_BS1_9tq ((unsigned char)0x08) /*!< 9 time quantum */ #define CAN_BS1_10tq ((unsigned char)0x09) /*!< 10 time quantum */ #define CAN_BS1_11tq ((unsigned char)0x0A) /*!< 11 time quantum */ #define CAN_BS1_12tq ((unsigned char)0x0B) /*!< 12 time quantum */ #define CAN_BS1_13tq ((unsigned char)0x0C) /*!< 13 time quantum */ #define CAN_BS1_14tq ((unsigned char)0x0D) /*!< 14 time quantum */ #define CAN_BS1_15tq ((unsigned char)0x0E) /*!< 15 time quantum */ #define CAN_BS1_16tq ((unsigned char)0x0F) /*!< 16 time quantum */ #define CAN_BS2_1tq ((unsigned char)0x00) /*!< 1 time quantum */ #define CAN_BS2_2tq ((unsigned char)0x01) /*!< 2 time quantum */ #define CAN_BS2_3tq ((unsigned char)0x02) /*!< 3 time quantum */ #define CAN_BS2_4tq ((unsigned char)0x03) /*!< 4 time quantum */ #define CAN_BS2_5tq ((unsigned char)0x04) /*!< 5 time quantum */ #define CAN_BS2_6tq ((unsigned char)0x05) /*!< 6 time quantum */ #define CAN_BS2_7tq ((unsigned char)0x06) /*!< 7 time quantum */ #define CAN_BS2_8tq ((unsigned char)0x07) /*!< 8 time quantum */ #define CAN_Id_Standard 0 #define CAN_Id_Extended 1 #define CAN_RTR_DATA 0 #define CAN_RTR_Remote 1 /*!< CAN 控制状态寄存器 */ /************************** CAN_MOD 寄存器位定义*******************************/ #define CAN_Mode_RM ((unsigned char)0x01) /*!< 复位模式 */ #define CAN_Mode_LOM ((unsigned char)0x02) /*!< 只听模式 1:只听 0:正常 */ #define CAN_Mode_STM ((unsigned char)0x04) /*!< 正常工作模式1:自检测 0:正常 */ #define CAN_Mode_AFM ((unsigned char)0x08) /*!< 单/双滤波模式 1:单 0: 双*/ #define CAN_Mode_SM ((unsigned char)0x10) /*!< 睡眠模式1: 睡眠 0: 唤醒 */ /************************** CAN_CMR 寄存器位定义*******************************/ #define CAN_CMR_TR ((unsigned char)0x01) /*!< 发送请求 1: 当前信息被发送 0: 空 */ #define CAN_CMR_AT ((unsigned char)0x02) /*!< 中止发送 1: 等待发送的信息取消 0: 空缺 */ #define CAN_CMR_RRB ((unsigned char)0x04) /*!< 释放接收缓冲器 1:释放 0: 无动作 */ #define CAN_CMR_CDO ((unsigned char)0x08) /*!< 清除数据溢出 1:清除 0: 无动作 */ //#define CAN_CMR_GTS ((unsigned char)0x10) /*!STD模式< 睡眠: 1:进入睡眠 0: 唤醒 */ #define CAN_CMR_SRR ((unsigned char)0x10) /*!< 自接收请求 1: 0: */ #define CAN_CMR_EFF ((unsigned char)0x80) /*!< 扩展模式 1:扩展帧 0: 标准帧 */ /************************** CAN_SR 寄存器位定义********************************/ #define CAN_SR_BBS ((unsigned char)0x01) /*!< 接收缓存器状态1: 满 0: 空 */ #define CAN_SR_DOS ((unsigned char)0x02) /*!< 数据溢出状态 1: 溢出 0: 空缺 */ #define CAN_SR_TBS ((unsigned char)0x04) /*!< 发送缓存器状态1: 释放 0: 锁定 */ #define CAN_SR_TCS ((unsigned char)0x08) /*!< 发送完毕状态1: 完毕 0: 未完毕 */ #define CAN_SR_RS ((unsigned char)0x10) /*!< 接收状态1: 接收 0: 空闲 */ #define CAN_SR_TS ((unsigned char)0x20) /*!< 发送状态1: 发送 0: 空闲*/ #define CAN_SR_ES ((unsigned char)0x40) /*!< 出错状态1:出错 0: 正常 */ #define CAN_SR_BS ((unsigned char)0x80) /*!< 总线状态1: 关闭 0: 开启 */ /************************** CAN_IR 中断寄存器位定义****************************/ #define CAN_IR_RI ((unsigned char)0x01) /*!< 接收中断 */ #define CAN_IR_TI ((unsigned char)0x02) /*!< 发送中断 */ #define CAN_IR_EI ((unsigned char)0x04) /*!< 错误中断 */ #define CAN_IR_DOI ((unsigned char)0x08) /*!< 数据溢出中断 */ #define CAN_IR_WUI ((unsigned char)0x10) /*!< 唤醒中断 */ #define CAN_IR_EPI ((unsigned char)0x20) /*!< 错误消极中断 */ #define CAN_IR_ALI ((unsigned char)0x40) /*!< 仲裁丢失中断 */ #define CAN_IR_BEI ((unsigned char)0x80) /*!< 总线错误中断 */ /************************* CAN_IER 中断使能寄存器位定义************************/ #define CAN_IER_RIE ((unsigned char)0x01) /*!< 接收中断使能 */ #define CAN_IER_TIE ((unsigned char)0x02) /*!< 发送中断使能 */ #define CAN_IER_EIE ((unsigned char)0x04) /*!< 错误中断使能 */ #define CAN_IER_DOIE ((unsigned char)0x08) /*!< 数据溢出中断使能 */ #define CAN_IER_WUIE ((unsigned char)0x10) /*!< 唤醒中断使能 */ #define CAN_IER_EPIE ((unsigned char)0x20) /*!< 错误消极中断使能 */ #define CAN_IER_ALIE ((unsigned char)0x40) /*!< 仲裁丢失中断使能 */ #define CAN_IER_BEIE ((unsigned char)0x80) /*!< 总线错误中断使能 */ typedef enum { CAN1MBaud=0, // 1 MBit/sec CAN800kBaud, // 800 kBit/sec CAN500kBaud, // 500 kBit/sec CAN250kBaud, // 250 kBit/sec CAN125kBaud, // 125 kBit/sec CAN100kBaud, // 100 kBit/sec CAN50kBaud, // 50 kBit/sec CAN40kBaud, // 40 kBit/sec }Ls1c_CanBPS_t; typedef struct { unsigned char MOD; unsigned char CMR; unsigned char SR; unsigned char IR; unsigned char IER; unsigned char reserved0; unsigned char BTR0; unsigned char BTR1; unsigned char OCR; unsigned char reserved[2]; unsigned char ALC; unsigned char ECC ; unsigned char EMLR; unsigned char RXERR; unsigned char TXERR; unsigned char IDE_RTR_DLC; unsigned char ID[4]; unsigned char BUF[8]; unsigned char RMCR; unsigned char CDR; } CAN_TypeDef; typedef struct { unsigned char CAN_Prescaler; /* 波特率分频系数1 to 31. */ unsigned char CAN_Mode; /*0x10:睡眠0x08:单,双滤波 0x40:正常工作0x20:只听 0x01:复位*/ unsigned char CAN_SJW; /*同步跳转宽度 */ unsigned char CAN_BS1; /*时间段1计数值*/ unsigned char CAN_BS2; /*时间段2计数值*/ } CAN_InitTypeDef; typedef struct { unsigned char CAN_FilterId0; /*验收代码0*/ unsigned char CAN_FilterMaskId0; /*验收屏蔽0*/ unsigned char CAN_FilterId1; /*验收代码1*/ unsigned char CAN_FilterMaskId1; /*验收屏蔽1*/ unsigned char CAN_FilterId2; /*验收代码2*/ unsigned char CAN_FilterMaskId2; /*验收屏蔽2*/ unsigned char CAN_FilterId3; /*验收代码3*/ unsigned char CAN_FilterMaskId3; /*验收屏蔽3*/ } CAN_FilterInitTypeDef; typedef struct { unsigned long StdId; /* 11位ID*/ unsigned long ExtId; /*29位ID**/ unsigned char IDE; /*IDE: 标识符选择 该位决定发送邮箱中报文使用的标识符类型 0: 使用标准标识符 1: 使用扩展标识符*/ unsigned char RTR; /*远程发送请求 0: 数据帧 1: 远程帧*/ unsigned char DLC; /*数据帧长度*/ unsigned char Data[8]; /*8字节数据*/ } CanRxMsg; typedef struct { unsigned long StdId; /* 11位ID*/ unsigned long ExtId; /*29位ID**/ unsigned char IDE; /*IDE: 标识符选择 该位决定发送邮箱中报文使用的标识符类型 0: 使用标准标识符 1: 使用扩展标识符*/ unsigned char RTR; /*远程发送请求 0: 数据帧 1: 远程帧*/ unsigned char DLC; /*数据帧长度*/ unsigned char Data[8]; /*8字节数据*/ } CanTxMsg; unsigned char CAN_Init(CAN_TypeDef* CANx, CAN_InitTypeDef* CAN_InitStruct); void CAN_FilterInit(CAN_TypeDef* CANx, CAN_FilterInitTypeDef* CAN_FilterInitStruct); unsigned char CAN_Transmit(CAN_TypeDef* CANx, CanTxMsg* TxMessage); void CAN_Receive(CAN_TypeDef* CANx, CanRxMsg* RxMessage); #endif