CharlieJo 发表于 2024-8-5 16:19:18

can通信问题

本人使用的是STC32G8K64型号的芯片和STM32F303进行can通信,STM32F303作为数据发动段,STC32G8K64作为读取和处理数据端。can波特率为500kHz,接收端的程序是仿照着官方例程来写的。但是在通信过程中无法接收到数据。通过调试发现接收端程序无法进入到if(B_Can1Read){}判断里面,我尝试着用串口打印CAN状态寄存器(SR)的值,发现会返回0x22和0x2A两个值,通过查看STC32G8的芯片手册发现
CAN状态寄存器(SR)中的B1位始终为1,即ES:CAN模块错误状态位始终为1。但是对于芯片手册中关于这一位的描述有点摸不着头脑:该位为1时表示"CAN模块至少有一个错误寄存器的值达到或超过了96",但是在芯片手册中找了一段时间发现没有对can的错误寄存器进行叙述。现求教论坛内的大佬,知道这是什么原因吗?代码需要修改哪里才能成功实现两块芯片之间的can通信?


//相关宏定义

#define TSG1    2                //0~15
#define TSG2    1                //1~7 (TSG2 不能设置为0)
#define BRP   3                //0~63
#define SJW   0                //重新同步跳跃宽度
#define SAM   0                //总线电平采样次数: 0:采样1次; 1:采样3次


//can波特率设置函数
void CANSetBaudrate()
{
        CanWriteReg(BTR0,(SJW << 6) + BRP);
        CanWriteReg(BTR1,(SAM << 7) + (TSG2 << 4) + TSG1);
}


void app_can_init(void)
{
    CANEN = 1;          //CAN1模块使能
    CANSEL = 0;         //选择CAN1模块
    P_SW1 = (P_SW1 & ~(3<<4)) | (0<<4);
    CanWriteReg(MR,0x04);//使能 Reset Mode
    CANSetBaudrate();        //设置波特率

    //不进行滤波,接收所有报文
    CanWriteReg(ACR0,0x00);                //总线验收代码寄存器
    CanWriteReg(ACR1,0x00);
    CanWriteReg(ACR2,0x00);
    CanWriteReg(ACR3,0x00);
    CanWriteReg(AMR0,0xFF);                //总线验收屏蔽寄存器
    CanWriteReg(AMR1,0xFF);
    CanWriteReg(AMR2,0xFF);
    CanWriteReg(AMR3,0xFF);
    CanWriteReg(IMR ,0xff);                //中断寄存器
    CanWriteReg(ISR ,0xff);                //清中断标志
    CanWriteReg(MR,0x01);//退出 Reset Mode, 采用单滤波设置(设置过滤器后注意选择滤波模式)



    CANICR = 0x02;//CAN中断使能
}



//can通信处理函数
void vApp_Can_Process(void)
{
        u8 n,i,j;
        u8 sr;
    if(msecond >= 1000)   //1秒到
    {
      msecond = 0;
      sr = CanReadReg(SR);
      printf("%#x\r\n", sr);
      if(sr & 0x01)                //判断是否有 BS:BUS-OFF状态
      {
            CANAR = MR;

            CANDR &= ~0x04;//清除 Reset Mode, 从BUS-OFF状态退出
      }
    }




    if(B_Can1Read)//判断 CAN1 是否接收到数据
    {
      B_Can1Read = 0;
      //CANSEL = CAN1;                //选择CAN1模块
      n = CanReadMsg(CAN1_Rx);    //读取接收内容
      if(n>0)
      {


            for(i=0;i<n;i++)
            {
                // CanSendMsg(&CAN1_Rx);//CAN总线原样返回
                printf("CAN1 ID=0x%08lX DLC=%d FF=%d RTR=%d ",CAN1_Rx.ID,CAN1_Rx.DLC,CAN1_Rx.FF,CAN1_Rx.RTR);   //串口打印帧信息
                for(j=0;j<CAN1_Rx.DLC;j++)

                {
                  printf("0x%02X ",CAN1_Rx.DataBuffer);    //从串口输出收到的数据
                }
                printf("\r\n");



            }
      }
    }
}


//定时器配置函数

void Timer_config(void)
{
        TIM_InitTypeDef                TIM_InitStructure;                                                //结构定义
        TIM_InitStructure.TIM_Mode      = TIM_16BitAutoReload;        //指定工作模式,   TIM_16BitAutoReload,TIM_16Bit,TIM_8BitAutoReload,TIM_16BitAutoReloadNoMask
        TIM_InitStructure.TIM_ClkSource = TIM_CLOCK_1T;                //指定时钟源,   TIM_CLOCK_1T,TI


        TIM_InitStructure.TIM_ClkOut    = DISABLE;                                //是否输出高速脉冲, ENABLE或DISABLE
        TIM_InitStructure.TIM_Value   = (u16)(65536UL - (MAIN_Fosc / 1000UL));                //中断频率, 1000次/秒
        TIM_InitStructure.TIM_PS      = 0;                                        //8位预分频器(n+1), 0~255
        TIM_InitStructure.TIM_Run       = ENABLE;                                //是否初始化后启动定时器, ENABLE或D


        Timer_Inilize(Timer0,&TIM_InitStructure);                                //初始化Timer0          Timer0,Timer1,Timer2,Timer3,Timer4
        NVIC_Timer0_Init(ENABLE,Priority_0);                //中断使能, ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3
}



//定时器中断函数

void Timer0_ISR_Handler (void) interrupt TMR0_VECTOR                //锟斤拷锟叫讹拷时锟窖撅拷锟斤拷锟斤拷锟斤拷?
{
    msecond++;
}


//main函数

void main(void)
{
        WTST = 0;                //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
        EAXSFR();                //扩展SFR(XFR)访问使能
        CKCON = 0;      //提高访问XRAM速度

        // GPIO_config();
      P1_MODE_IO_PU(GPIO_Pin_0 | GPIO_Pin_1);



      Timer_config();
      UART_config();
      app_can_init();
        EA = 1;



      B_Can1Send = 0;
        while (1)
        {
            vApp_Can_Process();

      }
}

乘风飞扬 发表于 2024-8-5 18:40:53

建议先直接使用例程包里面的CAN总线收发例子测试,最多修改一下脚位通道,收发功能测试正常后再进行修改或者移植。

CharlieJo 发表于 2024-8-5 19:08:19

乘风飞扬 发表于 2024-8-5 18:40
建议先直接使用例程包里面的CAN总线收发例子测试,最多修改一下脚位通道,收发功能测试正常后再进行修改或 ...

乘风大佬,两块芯片集成在一个开发板上面,不太好做测试,而且手头上没有现成的STC开发板,准备使用pcan-view这个PC端软件来测试STC程序是否正确然后在进行后续的问题排查

CharlieJo 发表于 2024-8-6 14:50:42

乘风飞扬 发表于 2024-8-5 18:40
建议先直接使用例程包里面的CAN总线收发例子测试,最多修改一下脚位通道,收发功能测试正常后再进行修改或 ...

乘风大佬,今天参考了官方的can通信例程,can通信选择can1模块,串口选择串口2打印,但是烧入程序后仍然无法实现通信,后来用示波器测量can1_Tx引脚,发现始终都保持高电平但是我的程序里面引脚初始化已经写了CAN1_SW(CAN1_P00_P01),也进行了相应的初始化(初始化代码就是官方例程的代码,没有改动),请问出现这样的现象可能是什么原因?

乘风飞扬 发表于 2024-8-6 15:56:23

CharlieJo 发表于 2024-8-6 14:50
乘风大佬,今天参考了官方的can通信例程,can通信选择can1模块,串口选择串口2打印,但是烧入程序后仍然 ...

P00,P01的IO口模式需要设置。
此外进行CAN总线通信需要至少2个节点。
CAN_TX,CAN_RX通过收发器跟另外一个节点连接,才能正常进行通信测试。

CharlieJo 发表于 2024-8-7 17:09:14

乘风飞扬 发表于 2024-8-6 15:56
P00,P01的IO口模式需要设置。
此外进行CAN总线通信需要至少2个节点。
CAN_TX,CAN_RX通过收发器跟另外一 ...

乘风大佬,可以正常can通信了,问题出在can收发器上了,换了个新的can收发器就能正常收到stm32发来的数据了{:4_167:}

llyymm 发表于 2024-8-22 16:05:24

通信电缆上要并联一个120欧的电阻,不要忘记了

gdg.xxx 发表于 2025-1-6 15:38:22

请问楼主可不可以给我一份stc32g864的can通信代码

STC工程师 发表于 昨天 09:10

CharlieJo 发表于 2024-8-7 17:09
乘风大佬,可以正常can通信了,问题出在can收发器上了,换了个新的can收发器就能正常收到stm32发来的数据 ...

你好,仅仅是CAN收发器的问题吗?你用的是什么型号?
页: [1]
查看完整版本: can通信问题