找回密码
 立即注册
查看: 3986|回复: 3

CAN未能进入中断服务程序,求解

[复制链接]
  • 打卡等级:以坛为家II
  • 打卡总天数:449
  • 最近打卡:2025-05-01 08:38:15

12

主题

110

回帖

1072

积分

金牌会员

积分
1072
发表于 2023-3-13 21:51:33 | 显示全部楼层 |阅读模式
本帖最后由 gzlai 于 2023-3-13 21:56 编辑

CAN配置如下:

void CAN_config(void)
{
        CAN_InitTypeDef        CAN_InitStructure;                                        //结构定义


        CAN_InitStructure.CAN_Enable = ENABLE;                //CAN功能使能   ENABLE或DISABLE
        CAN_InitStructure.CAN_IMR = CAN_ALLIM;        //CAN中断寄存器         CAN_DOIM,CAN_BEIM,CAN_TIM,CAN_RIM,CAN_EPIM,CAN_EWIM,CAN_ALIM,CAN_ALLIM,DISABLE
        CAN_InitStructure.CAN_SJW = 0;                                        //重新同步跳跃宽度  0~3
        CAN_InitStructure.CAN_SAM = 0;                                        //总线电平采样次数  0:采样1次; 1:采样3次


                                                                                                        //CAN总线波特率=Fclk/((1+(TSG1+1)+(TSG2+1))*(BRP+1)*2)
        CAN_InitStructure.CAN_TSG1 = 2;                                        //同步采样段1       0~15
        CAN_InitStructure.CAN_TSG2 = 1;                                        //同步采样段2       1~7 (TSG2 不能设置为0)
        CAN_InitStructure.CAN_BRP = 15;                                        //波特率分频系数    0~63
                                                                                                        //24000000/((1+3+2)*16*2)=125KHz


        CAN_InitStructure.CAN_ACR0 = 0x00;                        //总线验收代码寄存器 0~0xFF
        CAN_InitStructure.CAN_ACR1 = 0x00;
        CAN_InitStructure.CAN_ACR2 = 0x00;
        CAN_InitStructure.CAN_ACR3 = 0x00;
        CAN_InitStructure.CAN_AMR0 = 0xff;                        //总线验收屏蔽寄存器 0~0xFF
        CAN_InitStructure.CAN_AMR1 = 0xff;
        CAN_InitStructure.CAN_AMR2 = 0xff;
        CAN_InitStructure.CAN_AMR3 = 0xff;
        CAN_Inilize(CAN1, &CAN_InitStructure);                        //CAN1 初始化


        NVIC_CAN_Init(CAN1, ENABLE, Priority_1);                //中断使能, CAN1/CAN2; ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3
}

我的任务函数是利用CAN发送轮询,具体如下:

portTASK_FUNCTION(vDCUTask, pvParameters)
{
        unsigned int DCUID = 0;//板内DCU编号
        unsigned int PICID;//存放功能码+地址码
        unsigned char sr;        
        unsigned char timeout_limit;
        unsigned char timeout_count = 0;
        unsigned char temp[11];
        unsigned char i;


        UNUSED(pvParameters);


        while (1)
        {
                while (DCUID < DCU_COUNT)//逐个DCU轮询
                {
                        PICID = 0x0004;//加入DCU实时数据读取功能码
                        PICID = (PICID << 7) + DCUID + 1ul;//加入DCU地址码
                        CANSEL = CAN1;                //选择CAN1模块
                        sr = CanReadReg(SR);//获取CAN状态
                        if (sr & 0x01)                //判断是否有 BS:BUS-OFF状态
                        {
                                CANAR = MR;
                                CANDR &= ~0x04;  //清除 Reset Mode, 从BUS-OFF状态退出
                        }
                        else
                        {
                                B_Can1Send = 1;
                                CMDFromPEDCToDCU(PICID);//发送轮询命令
                                while (B_Can1Send)//等待轮询命令发送完毕
                                {
                                        taskYIELD();
                                        P20 = 0;
                                }
                                P20 = 1;
                                timeout_limit = DCU_TIMEOUT_LIMIT;//设置等待反馈时间上限
                                while (timeout_limit--)//等待DCU反馈
                                {
                                        if (((sr & 0x88) == 0x80))//接收空闲并且接收BUFFER有数据帧
                                        {
                                                break;//直接退出等待
                                        }
                                        vTaskDelay(1);
                                }
                                if (timeout_limit == 0)//本次轮询反馈超时
                                {
                                        DCU_Timeout_Count[DCUID]++;//
                                       
                                }
                                else
                                {
                                        DCU_Timeout_Count[DCUID] = 0;
                                        CanReadFifo(temp);  //读取清除接收BUFFER
                                        for (i = 0; i < 8; i++)//接收到的数据放入DCU状态数组
                                        {
                                                DCU_State[DCUID] = temp[i + 3];
                                        }
                                }
                        }
                        DCUID++;//启动下一个DCU轮询
                }
                DCUID = 0;//复位轮询
        }
}


利用屠龙刀核心板调试上述代码时,发现发送数据的CAN1一直未能进入中断服务函数,在中断服务函数里设了断点也验证了程序未进入中断服务函数,请问是哪里漏了什么步骤吗?
CAN未能进入中断服务程序,求解-1.png







FreeRTOS-PEDC.zip

2.59 MB, 下载次数: 98

回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:415
  • 最近打卡:2025-04-30 09:58:34
已绑定手机

39

主题

2006

回帖

6841

积分

论坛元老

积分
6841
发表于 2023-3-14 10:19:22 | 显示全部楼层
我在你的代码中断函数里面加一个IO口翻转,通过示波器可以测出IO口翻转信号,说明进入中断是正常的。

此外,使用CAN总线测试工具也能抓到发送的轮询命令:
1.png
通过硬件仿真在中断函数里面加断点也能正常停止:
2.png
  • 打卡等级:以坛为家II
  • 打卡总天数:415
  • 最近打卡:2025-04-30 09:58:34
已绑定手机

39

主题

2006

回帖

6841

积分

论坛元老

积分
6841
发表于 2023-3-14 10:27:41 | 显示全部楼层
此外,CAN总线收发函数后来进行了优化,在官网STC32G库函数例程包、STC32G实验箱例程包里面的CAN总线例子上都已经进行了更新。
建议将新的方法移植过来,可提高收发效率,减少丢包可能。
  • 打卡等级:以坛为家II
  • 打卡总天数:449
  • 最近打卡:2025-05-01 08:38:15

12

主题

110

回帖

1072

积分

金牌会员

积分
1072
发表于 2023-3-14 22:44:21 | 显示全部楼层
今天把例程里的STC32G_CAN.h、STC32G_CAN.c、STC32_CAN_Isr.c全部替换到我自己的工程里,修改、测试完了,功能正常,非常感谢:handshake
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-2 02:25 , Processed in 0.246888 second(s), 66 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表