打印
[活动专区]

【AutoChips MCU 评测报告】+CAN基本收发通讯

[复制链接]
3810|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
今天我们测试一下AC7811的CAN功能。这里用的简易版本的USB-CAN(诺比特机器人)工具。
我们先把例程下载到MCU,例程写的非常好,架构很清晰,把收发放在一个定时器里面:
该实验主要功能:
上电后LED2,LED3处于熄灭状态,CAN配置正常模式,可接收可发送数据.
上电后,CAN以100ms的周期发送数据,连续发送2s时间后停止发送数据2s时间,依次循环.
当CAN接收到数据时,LED2以50ms的频率闪烁,300ms内没有接收到任何数据,LED2立即熄灭.
当CAN发送数据时,LED3以50ms的频率闪烁,当停止发送数据时,LED3立即熄灭.

CAN相关配置:      
CAN比特率为500K,标准数据帧格式,收发ID:
//2个允许接收的节点ID:
#define CAN1_RECV_DATA_ID1                        (0x220)
#define CAN1_RECV_DATA_ID2                        (0x230)
//一个标记本身的发送ID
#define CAN1_SEND_DATA_ID1                        (0x430)


CAN初始化代码:
void CAN_InitHardwr(void)
{
        CAN_Config canConfig = {0};
        CAN_BaudrateConfig canBandrateConfig = {0};
       
        GPIO_SetFunc(CAN1_TX, GPIO_FUNC_1);//设置CAN1引脚复用功能
        GPIO_SetFunc(CAN1_RX, GPIO_FUNC_1);
        GPIO_SetDir(CAN1_STB, GPIO_OUTPUT);//设置CAN1收发器控制为IO控制
        CAN1_TRASCVER_NML;//使能CAN收发器
       
        /*
        设置波特率为500K,采样点为81.25%.
        tSeg1 = (S_SEG_1 + 2); tSeg2 = (S_SEG_2 + 1).
        BandRate         = (48M / (S_PRESC + 1) / ((S_SEG_1 + 2) + (S_SEG_2 + 1)))
        SamplePoint = (tSeg1 / (tSeg1 + tSeg2)).
        在已经知道波特率与采样点的情况下,经过计算后:tSeg1 = 13,tSeg2 = 3.
         */
        canBandrateConfig.S_PRESC         = 5;//分频后时钟为8M.
        canBandrateConfig.S_SEG_1         = 11;
        canBandrateConfig.S_SEG_2         = 2;
        canBandrateConfig.S_SJW         = 2;//满足S_SJW <= tSeg2即可.
       
        /*
        16个过滤器中,可随意选择使用哪个,并制定其过滤模式,制定其过滤ID的类型.
        如果一个过滤器只需要接收一个ID,直接可将其设置CODE模式,然后根据ID类型设置过滤类型.
        如果一个过滤器需要接收多个ID,将其设置为MASK模式,并根据这几个ID的实际类型设置过滤ID类型,如果既有STD又有EXT,则应选择FILTER_IDE_STD_EXT_BOTH.
       
        此处加宏是为了更清楚的说明各种设置是否有效,在实际应用中,可将各种组合放在一起使用.
         */
        #if (RECV_FRM_KIND_SEL == ONLY_RECV_STD_FRM)
        CAN_SetFilterParam( 0, 1, CAN_FILTER_CODE_MODE, FILTER_IDE_STD_ONLY, CAN1_RECV_DATA_ID1);//使用CODE模式只接收STD帧
        CAN_SetFilterParam( 1, 1, CAN_FILTER_CODE_MODE, FILTER_IDE_STD_ONLY, CAN1_RECV_DATA_ID2);//使用CODE模式只接收STD帧
        #endif
        #if (RECV_FRM_KIND_SEL == ONLY_RECV_EXT_FRM)
        CAN_SetFilterParam( 0, 1, CAN_FILTER_CODE_MODE, FILTER_IDE_EXT_ONLY, CAN1_RECV_DATA_ID11);//使用CODE模式只接收EXT帧
        CAN_SetFilterParam( 1, 1, CAN_FILTER_CODE_MODE, FILTER_IDE_EXT_ONLY, CAN1_RECV_DATA_ID12);//使用CODE模式只接收EXT帧
        #endif
        #if (RECV_FRM_KIND_SEL == RECV_STD_EXT_BOTH_FRM)
        CAN_SetFilterParam( 0, 1, CAN_FILTER_MASK_MODE, FILTER_IDE_STD_EXT_BOTH, (CAN1_RECV_DATA_ID1 & CAN1_RECV_DATA_ID11));//使用MASK模式接收两种帧
        CAN_SetFilterParam( 1, 1, CAN_FILTER_MASK_MODE, FILTER_IDE_STD_EXT_BOTH, (CAN1_RECV_DATA_ID2 & CAN1_RECV_DATA_ID12));//使用MASK模式接收两种帧
        #endif
       
        canConfig.interruptEnable = TRUE;//使能中断
        canConfig.TSSS = TRUE;//使用次发送缓冲区发送
        canConfig.canMode = CAN_MODE_NORMAL;
        canConfig.autoReset = TRUE;//CAN BUSOFF后,自动恢复
        canConfig.filterList = g_canFilterTab;//赋值过滤器设置list
       
        CAN_SetEventCallBack(CAN1, CAN1_IRQnCallBack);
        CAN_Initialize(CAN1, &canConfig, &canBandrateConfig);
}
其中最关键的就是波特率和采样率的计时,详细可看参考手册,同时手册也给出了常见的通讯波特率的设置表格:

我们开始先配置USB-CAN的通讯相关的配置:


我们来验证一下,查看源码到底发送了什么。是否与接收到的匹配:
uint8_t                                        g_sendCANDataBuf[8] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88};
跟接受的数据一直,ID也是与#define CAN1_SEND_DATA_ID1        (0x430)匹配。
我们发送数据化,LED2会闪烁一会,然后熄灭。现象也正常。
下面我们稍微修改下,我们打印出接收的数据,并进行分析,如果就是到的数组第一个元素数值为1,就打开LED2,为2就关闭LED2。
直接在void CAN_CheckDataDealPrd(void)函数里面修改,接收部分的代码:
 if (g_recvedCANDataRdy)//数据接收后,处理
        {
                //复制数据到处理缓冲区,获取长度,ID信息
               
                g_recvedCANDataRdy = FALSE;
               
                //处理CAN数据
                printf("CAN RECEVIE DATA IS : 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x \r\n",g_recvCANMsgInfo.Data[0],
                        g_recvCANMsgInfo.Data[1],g_recvCANMsgInfo.Data[2],g_recvCANMsgInfo.Data[3],g_recvCANMsgInfo.Data[4],
                  g_recvCANMsgInfo.Data[5],g_recvCANMsgInfo.Data[6],g_recvCANMsgInfo.Data[7]);

                if(g_recvCANMsgInfo.Data[0]==1) {LED2_ON; printf("LED2 is on! \r\n");};
                if(g_recvCANMsgInfo.Data[0]==2) {LED2_OFF;printf("LED2 is off!\r\n");};
//                if (g_blinkLED2Flag == FALSE)//只有在当前没有闪烁灯的情况下,启动闪烁
//                {
//                        g_blinkLED2Flag = TRUE;
//                        g_blinkLED2TimeCnt = 0;
//                }
               
                g_recvStopTimeCnt = 0;
        }
//        else
//        {
//                if ((g_blinkLED2Flag) && (g_recvStopTimeCnt > 299))//300ms内没有接收到任何数据,停止闪烁
//                {
//                        g_blinkLED2Flag = FALSE;
//                       
//                        LED2_OFF;
//                }
//        }
编译下载,分别发送2串数据,现象如下:

同时LED也亮灭受控。
在这个架构上,我们就能完成一套基于CAN标志帧的简易通讯控制系统了。



使用特权

评论回复

相关帖子

沙发
chenjun89| | 2020-11-16 08:12 | 只看该作者
感谢楼主分享使用经验。

使用特权

评论回复
板凳
数据采集存储| | 2020-11-17 15:33 | 只看该作者
这个经验不错的,我认为需要好好学习一下技术思维。

使用特权

评论回复
地板
两只袜子| | 2020-11-18 09:14 | 只看该作者
技术大牛,多多指教

使用特权

评论回复
5
答案很长吧| | 2020-11-18 09:30 | 只看该作者
这个真的是技术大牛,厉害。学习了。

使用特权

评论回复
6
niaoniaoyuyin| | 2021-5-26 15:21 | 只看该作者
可以可以

使用特权

评论回复
7
单片小菜| | 2021-5-26 22:28 | 只看该作者
真是技术大牛,不错的想法。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

111

主题

627

帖子

2

粉丝