diff --git a/bsp/ls1cdev/drivers/drv_can.c b/bsp/ls1cdev/drivers/drv_can.c new file mode 100644 index 0000000000..bdcecc0d37 --- /dev/null +++ b/bsp/ls1cdev/drivers/drv_can.c @@ -0,0 +1,542 @@ +/* + * File : drv_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 +#include +#include +#include + +#include + + +#include "ls1c.h" +#include "ls1c_public.h" +#include "ls1c_regs.h" +#include "ls1c_clock.h" +#include "ls1c_can.h" +#include "ls1c_pin.h" + + +#ifdef RT_USING_CAN + +CanRxMsg RxMessage; + +struct ls1c_bxcan +{ + CAN_TypeDef *reg; + void * irq; +}; + +static rt_err_t bxmodifyfilter(struct ls1c_bxcan *pbxcan, struct rt_can_filter_item *pitem, rt_uint32_t actived) +{ + rt_int32_t fcase; + rt_err_t res; + rt_int32_t hdr, fbase, foff; + CAN_TypeDef* CANx; + CANx = pbxcan->reg; + + /*pitem->mode 1-掩码模式; 0- 滤波器模式 SJA1000中使用以下方式*/ + /*SJA1000中AFM 1-单滤波器模式; 0- 双滤波器模式 */ + + fcase = pitem->mode;/*1-单滤波器模式; 0- 双滤波器模式*/ + { + if (!actived) + { + return RT_EOK; + } + else if (pitem->hdr == -1) + { + res = -1; + if (res != RT_EOK) + { + return res; + } + } + else if (pitem->hdr >= 0) + { + rt_enter_critical(); + res = RT_EOK; + if (res != RT_EOK) + { + return res; + } + hdr = pitem->hdr; + rt_exit_critical(); + } + } + + CAN_FilterInitTypeDef CAN_FilterInitStruct; + unsigned char ide, rtr, id , idmask, mode; + ide = (unsigned char) pitem->ide; + rtr = (unsigned char) pitem->rtr; + id = pitem->id; + idmask = pitem->mask; + mode = (unsigned char) pitem->mode; + CAN_FilterInitStruct.IDE = ide; + CAN_FilterInitStruct.RTR = rtr; + CAN_FilterInitStruct.ID = id; + CAN_FilterInitStruct.IDMASK = idmask; + CAN_FilterInitStruct.MODE = mode; + CAN_FilterInit(CANx, &CAN_FilterInitStruct); + + return RT_EOK; +} + +static rt_err_t setfilter(struct ls1c_bxcan *pbxcan, struct rt_can_filter_config *pconfig) +{ + struct rt_can_filter_item *pitem = pconfig->items; + rt_uint32_t count = pconfig->count; + rt_err_t res; + while (count) + { + res = bxmodifyfilter(pbxcan, pitem, pconfig->actived); + if (res != RT_EOK) + { + return res; + } + pitem++; + count--; + } + return RT_EOK; +} +static void bxcan0_filter_init(struct rt_can_device *can) +{ + struct ls1c_bxcan *pbxcan; + pbxcan = (struct ls1c_bxcan *) can->parent.user_data; + +} + +static void bxcan1_filter_init(struct rt_can_device *can) +{ + struct ls1c_bxcan *pbxcan; + pbxcan = (struct ls1c_bxcan *) can->parent.user_data; + +} + +static void bxcan_init(CAN_TypeDef *pcan, rt_uint32_t baud, rt_uint32_t mode) +{ + CAN_InitTypeDef CAN_InitStructure; + + Ls1c_CanBPS_t bps ; + + switch(baud) + { + case CAN1MBaud: + bps = LS1C_CAN1MBaud; + break; + case CAN800kBaud: + bps = LS1C_CAN800kBaud; + break; + case CAN500kBaud: + bps = LS1C_CAN500kBaud; + break; + case CAN250kBaud: + bps = LS1C_CAN250kBaud; + break; + case CAN125kBaud: + bps = LS1C_CAN125kBaud; + break; + case CAN50kBaud: + bps = LS1C_CAN40kBaud; + break; + default: + bps = LS1C_CAN250kBaud; + break; + } + + switch (mode) + { + case RT_CAN_MODE_NORMAL: + CAN_InitStructure.CAN_Mode = 0x00; + break; + case RT_CAN_MODE_LISEN: + CAN_InitStructure.CAN_Mode = CAN_Mode_LOM; + break; + case RT_CAN_MODE_LOOPBACK: + CAN_InitStructure.CAN_Mode = CAN_Mode_STM; + + break; + case RT_CAN_MODE_LOOPBACKANLISEN: + CAN_InitStructure.CAN_Mode = CAN_Mode_STM|CAN_Mode_LOM; + break; + } + CAN_InitStructure.CAN_SJW = CAN_SJW_1tq; + + switch (bps) + { + case LS1C_CAN1MBaud: + CAN_InitStructure.CAN_Prescaler = 9; + CAN_InitStructure.CAN_BS1 = CAN_BS1_4tq; + CAN_InitStructure.CAN_BS2 = CAN_BS2_2tq; + break; + case LS1C_CAN800kBaud: + CAN_InitStructure.CAN_Prescaler = 8; + CAN_InitStructure.CAN_BS1 = CAN_BS1_7tq; + CAN_InitStructure.CAN_BS2 = CAN_BS2_2tq; + break; + case LS1C_CAN500kBaud: + CAN_InitStructure.CAN_Prescaler = 9; + CAN_InitStructure.CAN_BS1 = CAN_BS1_11tq; + CAN_InitStructure.CAN_BS2 = CAN_BS2_2tq; + break; + case LS1C_CAN250kBaud: + CAN_InitStructure.CAN_Prescaler = 36; + CAN_InitStructure.CAN_BS1 = CAN_BS1_4tq; + CAN_InitStructure.CAN_BS2 = CAN_BS2_2tq; + break; + case LS1C_CAN125kBaud: + CAN_InitStructure.CAN_Prescaler = 36; + CAN_InitStructure.CAN_BS1 = CAN_BS1_11tq; + CAN_InitStructure.CAN_BS2 = CAN_BS2_2tq; + break; + case LS1C_CAN100kBaud: + CAN_InitStructure.CAN_Prescaler = 63; + CAN_InitStructure.CAN_BS1 = CAN_BS1_7tq; + CAN_InitStructure.CAN_BS2 = CAN_BS2_2tq; + break; + case LS1C_CAN50kBaud: + CAN_InitStructure.CAN_Prescaler = 63; + CAN_InitStructure.CAN_BS1 = CAN_BS1_16tq; + CAN_InitStructure.CAN_BS2 = CAN_BS2_3tq; + break; + default: //250K + CAN_InitStructure.CAN_Prescaler = 36; + CAN_InitStructure.CAN_BS1 = CAN_BS1_4tq; + CAN_InitStructure.CAN_BS2 = CAN_BS2_2tq; + break; + } + + CAN_Init(pcan, &CAN_InitStructure); +} + +#ifdef USING_BXCAN0 +static void bxcan0_hw_init(void) +{ + 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); +} +#endif + +#ifdef USING_BXCAN1 +static void bxcan1_hw_init(void) +{ + pin_set_purpose(56, PIN_PURPOSE_GPIO); + pin_set_purpose(57, PIN_PURPOSE_GPIO); + pin_set_remap(56, PIN_REMAP_DEFAULT); + pin_set_remap(57, PIN_REMAP_DEFAULT); +} +#endif + + +static rt_err_t configure(struct rt_can_device *can, struct can_configure *cfg) +{ + CAN_TypeDef *pbxcan; + + pbxcan = ((struct ls1c_bxcan *) can->parent.user_data)->reg; + if (pbxcan == CAN0) + { +#ifdef USING_BXCAN0 + bxcan0_hw_init(); + bxcan_init(pbxcan, cfg->baud_rate, cfg->mode); +#endif + } + else if (pbxcan == CAN1) + { +#ifdef USING_BXCAN1 + bxcan1_hw_init(); + bxcan_init(pbxcan, cfg->baud_rate, cfg->mode); +#endif + } + return RT_EOK; +} + +static rt_err_t control(struct rt_can_device *can, int cmd, void *arg) +{ + struct ls1c_bxcan *pbxcan; + rt_uint32_t argval; + + pbxcan = (struct ls1c_bxcan *) can->parent.user_data; + switch (cmd) + { + case RT_CAN_CMD_SET_FILTER: + return setfilter(pbxcan, (struct rt_can_filter_config *) arg); + break; + case RT_CAN_CMD_SET_MODE: + argval = (rt_uint32_t) arg; + if (argval != RT_CAN_MODE_NORMAL || + argval != RT_CAN_MODE_LISEN || + argval != RT_CAN_MODE_LOOPBACK || + argval != RT_CAN_MODE_LOOPBACKANLISEN) + { + return RT_ERROR; + } + if (argval != can->config.mode) + { + can->config.mode = argval; + return CAN_SetMode(pbxcan->reg, argval); + } + break; + case RT_CAN_CMD_SET_BAUD: + argval = (rt_uint32_t) arg; + if (argval != CAN1MBaud && + argval != CAN800kBaud && + argval != CAN500kBaud && + argval != CAN250kBaud && + argval != CAN125kBaud && + argval != CAN100kBaud && + argval != CAN50kBaud ) + { + return RT_ERROR; + } + if (argval != can->config.baud_rate) + { + can->config.baud_rate = argval; + Ls1c_CanBPS_t bps; + switch(argval) + { + case CAN1MBaud: + bps = LS1C_CAN1MBaud; + break; + case CAN800kBaud: + bps = LS1C_CAN800kBaud; + break; + case CAN500kBaud: + bps = LS1C_CAN500kBaud; + break; + case CAN250kBaud: + bps = LS1C_CAN250kBaud; + break; + case CAN125kBaud: + bps = LS1C_CAN125kBaud; + break; + case CAN50kBaud: + bps = LS1C_CAN40kBaud; + break; + default: + bps = LS1C_CAN250kBaud; + break; + } + return CAN_SetBps( pbxcan->reg, bps); + } + break; + case RT_CAN_CMD_GET_STATUS: + { + rt_uint32_t errtype; + + errtype = pbxcan->reg->RXERR; + can->status.rcverrcnt = errtype ; + errtype = pbxcan->reg->TXERR; + can->status.snderrcnt = errtype ; + errtype = pbxcan->reg->ECC; + can->status.errcode = errtype ; + if (arg != &can->status) + { + rt_memcpy(arg, &can->status, sizeof(can->status)); + } + } + break; + } + + return RT_EOK; +} + +static int sendmsg(struct rt_can_device *can, const void *buf, rt_uint32_t boxno) +{ + CAN_TypeDef *pbxcan; + CanTxMsg TxMessage; + struct rt_can_msg *pmsg = (struct rt_can_msg *) buf; + int i; + + pbxcan = ((struct ls1c_bxcan *) can->parent.user_data)->reg; + + TxMessage.StdId = pmsg->id; + TxMessage.ExtId = pmsg->id; + TxMessage.RTR = pmsg->rtr; + TxMessage.IDE = pmsg->ide; + TxMessage.DLC = pmsg->len; + for( i=0; idata[i]; + } + CAN_Transmit(pbxcan, &TxMessage); + + return RT_EOK; +} + +static int recvmsg(struct rt_can_device *can, void *buf, rt_uint32_t boxno) +{ + CAN_TypeDef *pbxcan; + + struct rt_can_msg *pmsg = (struct rt_can_msg *) buf; + int i; + + pbxcan = ((struct ls1c_bxcan *) can->parent.user_data)->reg; + + pmsg->ide = (rt_uint32_t) RxMessage.IDE; + if(RxMessage.IDE == 1) + pmsg->id = RxMessage.ExtId; + else + pmsg->id = RxMessage.StdId; + pmsg->len = RxMessage.DLC; + pmsg->rtr = RxMessage.RTR; + pmsg->hdr = 0; + for(i= 0;i< RxMessage.DLC; i++) + { + pmsg->data[i] = RxMessage.Data[i]; + } + return RT_EOK; +} + +static const struct rt_can_ops canops = +{ + configure, + control, + sendmsg, + recvmsg, +}; + +#ifdef USING_BXCAN0 +struct rt_can_device bxcan0; +void ls1c_can0_irqhandler(int irq, void *param) +{ + CAN_TypeDef* CANx; + unsigned char status; + CANx = CAN0; + /*读寄存器清除中断*/ + status = CANx->IR; + + /*接收中断*/ + if (( status & CAN_IR_RI) == CAN_IR_RI) + { + /*清除RI 中断*/ + CAN_Receive(CANx, &RxMessage); + CANx->CMR |= CAN_CMR_RRB; + CANx->CMR |= CAN_CMR_CDO; + rt_hw_can_isr(&bxcan0, RT_CAN_EVENT_RX_IND); + rt_kprintf("\r\nCan0 int RX happened!\r\n"); + } + /*发送中断*/ + else if (( status & CAN_IR_TI) == CAN_IR_TI) + { + rt_hw_can_isr(&bxcan0, RT_CAN_EVENT_TX_DONE | 0 << 8); + rt_kprintf("\r\nCan0 int TX happened!\r\n"); + } + /*数据溢出中断*/ + else if (( status & CAN_IR_TI) == CAN_IR_DOI) + { + rt_hw_can_isr(&bxcan0, RT_CAN_EVENT_RXOF_IND); + rt_kprintf("\r\nCan0 int RX OF happened!\r\n"); + } +} +static struct ls1c_bxcan bxcan0data = +{ + .reg = CAN0, + .irq = ls1c_can0_irqhandler, +}; +#endif /*USING_BXCAN0*/ + +#ifdef USING_BXCAN1 +struct rt_can_device bxcan1; +void ls1c_can1_irqhandler(int irq, void *param) +{ + CAN_TypeDef* CANx; + unsigned char status; + CANx = CAN1; + /*读寄存器清除中断*/ + status = CANx->IR; + + /*接收中断*/ + if (( status & CAN_IR_RI) == CAN_IR_RI) + { + /*清除RI 中断*/ + CAN_Receive(CANx, &RxMessage); + CANx->CMR |= CAN_CMR_RRB; + CANx->CMR |= CAN_CMR_CDO; + rt_hw_can_isr(&bxcan1, RT_CAN_EVENT_RX_IND); + rt_kprintf("\r\nCan1 int RX happened!\r\n"); + } + /*发送中断*/ + else if (( status & CAN_IR_TI) == CAN_IR_TI) + { + rt_hw_can_isr(&bxcan1, RT_CAN_EVENT_TX_DONE | 0 << 8); + rt_kprintf("\r\nCan1 int TX happened!\r\n"); + } + /*数据溢出中断*/ + else if (( status & CAN_IR_TI) == CAN_IR_DOI) + { + rt_hw_can_isr(&bxcan1, RT_CAN_EVENT_RXOF_IND); + rt_kprintf("\r\nCan1 int RX OF happened!\r\n"); + } +} +static struct ls1c_bxcan bxcan1data = +{ + .reg = CAN1, + .irq = ls1c_can1_irqhandler, +}; + +#endif /*USING_BXCAN1*/ + +int ls1c_bxcan_init(void) +{ + +#ifdef USING_BXCAN0 + bxcan0.config.baud_rate = CAN250kBaud; + bxcan0.config.msgboxsz = 1; + bxcan0.config.sndboxnumber = 1; + bxcan0.config.mode = RT_CAN_MODE_NORMAL; + bxcan0.config.privmode = 0; + bxcan0.config.ticks = 50; +#ifdef RT_CAN_USING_HDR + bxcan0.config.maxhdr = 2; +#endif + rt_hw_can_register(&bxcan0, "bxcan0", &canops, &bxcan0data); + rt_kprintf("\r\ncan0 register! \r\n"); + + rt_hw_interrupt_install(LS1C_CAN0_IRQ,( rt_isr_handler_t)bxcan0data.irq , RT_NULL, "can0"); + rt_hw_interrupt_umask(LS1C_CAN0_IRQ); +#endif +#ifdef USING_BXCAN1 + bxcan1.config.baud_rate = CAN250kBaud; + bxcan1.config.msgboxsz = 1; + bxcan1.config.sndboxnumber = 1; + bxcan1.config.mode = RT_CAN_MODE_NORMAL; + bxcan1.config.privmode = 0; + bxcan1.config.ticks = 50; +#ifdef RT_CAN_USING_HDR + bxcan1.config.maxhdr = 2; +#endif + rt_hw_can_register(&bxcan1, "bxcan1", &canops, &bxcan1data); + rt_kprintf("\r\ncan1 register! \r\n"); + + rt_hw_interrupt_install(LS1C_CAN1_IRQ,( rt_isr_handler_t)bxcan1data.irq , RT_NULL, "can1"); + rt_hw_interrupt_umask(LS1C_CAN1_IRQ); +#endif + return RT_EOK; +} + +INIT_BOARD_EXPORT(ls1c_bxcan_init); + +#endif /*RT_USING_CAN*/ diff --git a/bsp/ls1cdev/drivers/drv_can.h b/bsp/ls1cdev/drivers/drv_can.h new file mode 100644 index 0000000000..0d846dee25 --- /dev/null +++ b/bsp/ls1cdev/drivers/drv_can.h @@ -0,0 +1,30 @@ +/* + * File : bxcan.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: + * Date Author Notes + * 2018-01-06 sundm75 first version + */ + +#ifndef LS1C_DRV_CAN_H +#define LS1C_DRV_CAN_H + +extern int ls1c_bxcan_init(void); + +#endif /*DRV_CAN_H_*/ diff --git a/bsp/ls1cdev/libraries/Ls1c_can.c b/bsp/ls1cdev/libraries/Ls1c_can.c new file mode 100644 index 0000000000..3062e05253 --- /dev/null +++ b/bsp/ls1cdev/libraries/Ls1c_can.c @@ -0,0 +1,460 @@ +/* + * 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.h" +#include "ls1c_public.h" +#include "ls1c_can.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; + } + rt_kprintf("\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; + } + rt_kprintf("\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) + { + rt_kprintf("\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;iDLC; 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;iDLC-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]; + } +} + diff --git a/bsp/ls1cdev/libraries/Ls1c_can.h b/bsp/ls1cdev/libraries/Ls1c_can.h new file mode 100644 index 0000000000..393205ad38 --- /dev/null +++ b/bsp/ls1cdev/libraries/Ls1c_can.h @@ -0,0 +1,227 @@ + +/* + * 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 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 + +#define CAN_MODE_NORMAL 0 +#define CAN_MODE_LISEN 1 +#define CAN_MODE_LOOPBACK 2 +#define CAN_MODE_LOOPBACKANLISEN 3 + +/*!< 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 +{ + LS1C_CAN1MBaud=0, // 1 MBit/sec + LS1C_CAN800kBaud, // 800 kBit/sec + LS1C_CAN500kBaud, // 500 kBit/sec + LS1C_CAN250kBaud, // 250 kBit/sec + LS1C_CAN125kBaud, // 125 kBit/sec + LS1C_CAN100kBaud, // 100 kBit/sec + LS1C_CAN50kBaud, // 50 kBit/sec + LS1C_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 IDE; /*0: 使用标准标识符1: 使用扩展标识符*/ + unsigned char RTR; /*0: 数据帧 1: 远程帧*/ + unsigned char MODE; /* 0- 双滤波器模式;1-单滤波器模式*/ + unsigned long First_Data; /*双滤波器模式下信息第一个数据字节*/ + unsigned long Data_Mask; /*双滤波器模式下信息第一个数据字节屏蔽*/ + unsigned long ID; /*验收代码*/ + /* + 双滤波器- 扩展帧: 2个滤波器的前16位,分别放在ID 的前16位和 ID的后16位. + 双滤波器- 标准帧: 2个滤波器的11位,分别放在ID 的前16位和 ID的后16位,第1个滤波器同时使用First_Data和Data_Mask + 单滤波器- 扩展帧: 使用29位, 放在ID 的后29位. + 单滤波器- 标准帧: 使用11位, 放在ID 的后11位. + */ + unsigned long IDMASK; /*验收屏蔽*/ +} 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); +unsigned char CAN_SetBps(CAN_TypeDef* CANx, Ls1c_CanBPS_t Bps); +unsigned char CAN_SetMode(CAN_TypeDef* CANx, unsigned char mode); +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); + +unsigned char set_reset_mode(CAN_TypeDef* CANx); +unsigned char set_start(CAN_TypeDef* CANx); + +#endif + diff --git a/bsp/ls1cdev/libraries/ls1c_regs.h b/bsp/ls1cdev/libraries/ls1c_regs.h index 9d6c21dea6..630b45ccbe 100644 --- a/bsp/ls1cdev/libraries/ls1c_regs.h +++ b/bsp/ls1cdev/libraries/ls1c_regs.h @@ -1,4 +1,4 @@ -// о1cĴ +// 龙芯1c外设寄存器 #ifndef __OPENLOONGSON_LS1C_REGS_H @@ -7,12 +7,12 @@ -// ʱؼĴַ +// 时钟相关寄存器地址 #define LS1C_START_FREQ (0xbfe78030) #define LS1C_CLK_DIV_PARAM (0xbfe78034) -// gpioؼĴַ +// gpio相关寄存器地址 #define LS1C_GPIO_CFG0 (0xbfd010c0) #define LS1C_GPIO_EN0 (0xbfd010d0) #define LS1C_GPIO_IN0 (0xbfd010e0) @@ -35,7 +35,7 @@ -// ؼĴ +// 复用相关寄存器 #define LS1C_CBUS_FIRST0 (0xbfd011c0) #define LS1C_CBUS_SECOND0 (0xbfd011d0) #define LS1C_CBUS_THIRD0 (0xbfd011e0) @@ -61,20 +61,22 @@ #define LS1C_CBUS_FIFTH3 (0xbfd0120c) -// PWMĴƫ +// PWM寄存器偏移 #define LS1C_PWM_CNTR (0x0) #define LS1C_PWM_HRC (0x4) #define LS1C_PWM_LRC (0x8) #define LS1C_PWM_CTRL (0xC) -// PWMַ +// PWM基地址 #define LS1C_REG_BASE_PWM0 (0xbfe5c000) #define LS1C_REG_BASE_PWM1 (0xbfe5c010) #define LS1C_REG_BASE_PWM2 (0xbfe5c020) #define LS1C_REG_BASE_PWM3 (0xbfe5c030) +//CAN基地址 +#define LS1C_REG_BASE_CAN0 (0xbfe50000) +#define LS1C_REG_BASE_CAN1 (0xbfe54000) - -// жüĴ +// 中断配置寄存器 #define LS1C_INT0_SR (0xbfd01040) #define LS1C_INT0_EN (0xbfd01044) #define LS1C_INT0_SET (0xbfd01048) @@ -111,18 +113,18 @@ #define LS1C_INT4_EDGE (0xbfd010b4) -// I2CĴ +// I2C寄存器 #define LS1C_I2C0_BASE (0xbfe58000) #define LS1C_I2C1_BASE (0xbfe68000) #define LS1C_I2C2_BASE (0xbfe70000) -// SPIĴ +// SPI寄存器 #define LS1C_SPI0_BASE (0xbfe80000) #define LS1C_SPI1_BASE (0xbfec0000) -// ڼĴ +// 串口寄存器 #define LS1C_UART0_BASE (0xbfe40000) #define LS1C_UART1_BASE (0xbfe44000) #define LS1C_UART2_BASE (0xbfe48000)