gzlai 发表于 2023-3-13 21:51:33

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

本帖最后由 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;
      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++;//
                                       
                              }
                              else
                              {
                                        DCU_Timeout_Count = 0;
                                        CanReadFifo(temp);//读取清除接收BUFFER
                                        for (i = 0; i < 8; i++)//接收到的数据放入DCU状态数组
                                        {
                                                DCU_State = temp;
                                        }
                              }
                        }
                        DCUID++;//启动下一个DCU轮询
                }
                DCUID = 0;//复位轮询
      }
}


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








乘风飞扬 发表于 2023-3-14 10:19:22

我在你的代码中断函数里面加一个IO口翻转,通过示波器可以测出IO口翻转信号,说明进入中断是正常的。

此外,使用CAN总线测试工具也能抓到发送的轮询命令:

通过硬件仿真在中断函数里面加断点也能正常停止:

乘风飞扬 发表于 2023-3-14 10:27:41

此外,CAN总线收发函数后来进行了优化,在官网STC32G库函数例程包、STC32G实验箱例程包里面的CAN总线例子上都已经进行了更新。
建议将新的方法移植过来,可提高收发效率,减少丢包可能。

gzlai 发表于 2023-3-14 22:44:21

今天把例程里的STC32G_CAN.h、STC32G_CAN.c、STC32_CAN_Isr.c全部替换到我自己的工程里,修改、测试完了,功能正常,非常感谢:handshake
页: [1]
查看完整版本: CAN未能进入中断服务程序,求解