马永锋 发表于 2023-12-9 15:24:14

冲哥 子午鸳鸯钺 CAN测试救助


使用冲哥的子午鸳鸯钺,两组CAN进行连接,DEMO使用的函数的例程,对CAN的引脚进行了修改,其他代码没有修改。
目前无法printf。下图为连接方式。


代码如下
/*---------------------------------------------------------------------*/
/* --- STC MCU Limited ------------------------------------------------*/
/* --- STC 1T Series MCU Demo Programme -------------------------------*/
/* --- Mobile: (86)13922805190 ----------------------------------------*/
/* --- Fax: 86-0513-55012956,55012947,55012969 ------------------------*/
/* --- Tel: 86-0513-55012928,55012929,55012966 ------------------------*/
/* --- Web: www.STCAI.com ---------------------------------------------*/
/* --- Web: www.STCMCUDATA.com---------------------------------------*/
/* --- BBS: www.STCAIMCU.com-----------------------------------------*/
/* --- QQ:800003751 -------------------------------------------------*/
/* 如果要在程序中使用此代码,请在程序中注明使用了STC的资料及程序            */
/*---------------------------------------------------------------------*/

#include        "STC32G_CAN.h"
#include        "STC32G_GPIO.h"
#include        "STC32G_NVIC.h"
#include        "STC32G_UART.h"
#include        "STC32G_Timer.h"
#include        "STC32G_Switch.h"

/*************   功能说明   ***************

CAN1、CAN2总线同时使用收发测试用例.

DCAN是一个支持CAN2.0B协议的功能单元。

收到一帧数据后, 通过串口1(P3.0,P3.1)发送出去,串口参数:115200,N,8,1.

需要在"STC32G_UART.h"里设置: #define        PRINTF_SELECTUART1

MCU每秒钟从CAN1、CAN2发送一帧固定数据,每发一帧ID号加1.

CAN2设置单滤波模式,只接收ID为 0x280~0x2ff 的标准帧报文

默认CAN总线波特率500KHz, 用户可自行修改.

下载时, 选择时钟 24MHz (用户可在"config.h"修改频率).

******************************************/

/*************        本地常量声明        **************/


/*************        本地变量声明        **************/

u16 msecond;

/*************        本地函数声明        **************/


/*************外部函数和变量声明 *****************/


/******************** IO口配置 ********************/
void GPIO_config(void)
{
        P3_MODE_IO_PU(GPIO_Pin_0 | GPIO_Pin_1);                //P3.0,P3.1 设置为准双向口
        P0_MODE_IO_PU(GPIO_Pin_LOW);                //P0.0~P0.3 设置为准双向口

        CAN1_SW(CAN1_P00_P01);                                //CAN1_P00_P01,CAN1_P50_P51,CAN1_P42_P45,CAN1_P70_P71
        CAN2_SW(CAN2_P02_P03);                                //CAN2_P02_P03,CAN2_P52_P53,CAN2_P46_P47,CAN2_P72_P73
}

/************************ 定时器配置 ****************************/
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,TIM_CLOCK_12T,TIM_CLOCK_Ext
        TIM_InitStructure.TIM_ClkOut    = DISABLE;                                //是否输出高速脉冲, ENABLE或DISABLE
        TIM_InitStructure.TIM_Value   = (u16)(65536UL - (MAIN_Fosc / 1000UL));                //初值, 1秒钟中断1000次
        TIM_InitStructure.TIM_PS      = 0;                                        //8位预分频器(n+1), 0~255
        TIM_InitStructure.TIM_Run       = ENABLE;                                //是否初始化后启动定时器, ENABLE或DISABLE
        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 UART_config(void)
{
        COMx_InitDefine                COMx_InitStructure;                                        //结构定义

        COMx_InitStructure.UART_Mode      = UART_8bit_BRTx;                //模式,   UART_ShiftRight,UART_8bit_BRTx,UART_9bit,UART_9bit_BRTx
        COMx_InitStructure.UART_BRT_Use   = BRT_Timer2;                        //选择波特率发生器, BRT_Timer2 (注意: 串口2固定使用BRT_Timer2, 所以不用选择)
        COMx_InitStructure.UART_BaudRate= 115200ul;                        //波特率,   110 ~ 115200
        COMx_InitStructure.UART_RxEnable= ENABLE;                                //接收允许,   ENABLE或DISABLE
        UART_Configuration(UART1, &COMx_InitStructure);                //初始化串口 USART1,USART2,USART3,USART4
        NVIC_UART1_Init(ENABLE,Priority_1);                //中断使能, ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3

        UART1_SW(UART1_SW_P30_P31);                //UART1_SW_P30_P31,UART1_SW_P36_P37,UART1_SW_P16_P17,UART1_SW_P43_P44
}

/******************** 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    = 3;                        //波特率分频系数    0~63
        //24000000/((1+3+2)*4*2)=500KHz

        CAN_InitStructure.CAN_ListenOnly = DISABLE;        //Listen Only模式   ENABLE,DISABLE
        CAN_InitStructure.CAN_Filter= SINGLE_FILTER;//滤波选择DUAL_FILTER(双滤波),SINGLE_FILTER(单滤波)
        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 初始化

    //只接收 ID 为 0x280 ~ 0x2ff 的标准帧报文
    CAN_InitStructure.CAN_ACR0    = 0x50;                //总线验收代码寄存器 0~0xFF
        CAN_InitStructure.CAN_ACR1    = 0x00;
        CAN_InitStructure.CAN_ACR2    = 0x00;
        CAN_InitStructure.CAN_ACR3    = 0x00;
        CAN_InitStructure.CAN_AMR0    = 0x0f;                //总线验收屏蔽寄存器 0~0xFF
        CAN_InitStructure.CAN_AMR1    = 0xef;
        CAN_InitStructure.CAN_AMR2    = 0xff;
        CAN_InitStructure.CAN_AMR3    = 0xff;
        CAN_Inilize(CAN2,&CAN_InitStructure);                //CAN2 初始化
       
        NVIC_CAN_Init(CAN1,ENABLE,Priority_1);                //中断使能, CAN1/CAN2; ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3
        NVIC_CAN_Init(CAN2,ENABLE,Priority_1);                //中断使能, CAN1/CAN2; ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3
}

/**********************************************/
void main(void)
{
        u8 n,i,j;
        u8 sr;

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

        GPIO_config();
    Timer_config();
    UART_config();
        CAN_config();
        EA = 1;
        //====初始化数据=====
        CAN1_Tx.FF = STANDARD_FRAME;    //标准帧
        CAN1_Tx.RTR = 0;                //0:数据帧,1:远程帧
        CAN1_Tx.DLC = 0x08;             //数据长度
//        CAN1_Tx.ID = 0x02f8;            //CAN ID
        CAN1_Tx.ID = 0x0278;            //CAN ID
        CAN1_Tx.DataBuffer = 0x11;   //数据内容
        CAN1_Tx.DataBuffer = 0x12;
        CAN1_Tx.DataBuffer = 0x13;
        CAN1_Tx.DataBuffer = 0x14;
        CAN1_Tx.DataBuffer = 0x15;
        CAN1_Tx.DataBuffer = 0x16;
        CAN1_Tx.DataBuffer = 0x17;
        CAN1_Tx.DataBuffer = 0x18;
       
        CAN2_Tx.FF = EXTENDED_FRAME;    //扩展帧
        CAN2_Tx.RTR = 0;                //0:数据帧,1:远程帧
        CAN2_Tx.DLC = 0x08;             //数据长度
        CAN2_Tx.ID = 0x03456789;      //CAN ID
        CAN2_Tx.DataBuffer = 0x21;   //数据内容
        CAN2_Tx.DataBuffer = 0x22;
        CAN2_Tx.DataBuffer = 0x23;
        CAN2_Tx.DataBuffer = 0x24;
        CAN2_Tx.DataBuffer = 0x25;
        CAN2_Tx.DataBuffer = 0x26;
        CAN2_Tx.DataBuffer = 0x27;
        CAN2_Tx.DataBuffer = 0x28;

        while (1)
        {
      if(T0_1ms)
      {
            T0_1ms = 0;
            //------------------处理CAN1模块-----------------------
            if(++msecond >= 1000)   //1秒到
            {
                msecond = 0;

                CANSEL = CAN1;                //选择CAN1模块
                sr = CanReadReg(SR);

                if(sr & 0x01)                //判断是否有 BS:BUS-OFF状态
                {
                  CANAR = MR;
                  CANDR &= ~0x04;//清除 Reset Mode, 从BUS-OFF状态退出
                }
                else
                {
                  CanSendMsg(&CAN1_Tx);   //发送一帧数据
                  CAN1_Tx.ID += 0x01;      //CAN ID
                }

//                //------------------处理CAN2模块-----------------------
                CANSEL = CAN2;                //选择CAN2模块
                sr = CanReadReg(SR);

                if(sr & 0x01)                //判断是否有 BS:BUS-OFF状态
                {
                  CANAR = MR;
                  CANDR &= ~0x04;//清除 Reset Mode, 从BUS-OFF状态退出
                }
                else
                {
                  CanSendMsg(&CAN2_Tx);   //发送一帧数据
                  CAN2_Tx.ID += 0x0001;      //CAN ID
                }
            }
      }

                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");
                }
            }
                }

                if(B_Can2Read)      //判断 CAN2 是否接收到数据
                {
                        B_Can2Read = 0;
                       
                        CANSEL = CAN2;                //选择CAN2模块
            n = CanReadMsg(CAN2_Rx);    //读取接收内容
            if(n>0)
            {
                for(i=0;i<n;i++)
                {
//                  CanSendMsg(&CAN2_Rx);//CAN总线原样返回
                  printf("CAN2 ID=0x%08lX DLC=%d FF=%d RTR=%d ",CAN2_Rx.ID,CAN2_Rx.DLC,CAN2_Rx.FF,CAN2_Rx.RTR);   //串口打印帧信息
                  for(j=0;j<CAN2_Rx.DLC;j++)
                  {
                        printf("0x%02X ",CAN2_Rx.DataBuffer);    //从串口输出收到的数据
                  }
                  printf("\r\n");
                }
            }
                }
        }
}


马永锋 发表于 2023-12-10 12:07:56

昨天CAN测试的问题找到了,由于没有开启120欧姆电阻导致异常。
下面是今天的测试,STC强大。

attach://29182.mp4

神农鼎 发表于 2023-12-10 12:34:38

估计总有一天,你会用这 2组 CAN 去造车,不是检测保养美容

恍如隔世 发表于 2024-10-8 08:40:01

楼主,源码分享一下

乘风飞扬 发表于 2024-10-8 13:39:09

恍如隔世 发表于 2024-10-8 08:40
楼主,源码分享一下

官网、论坛都有CAN总线通信例子可以参考。
STC32G实验箱例程包,或者屠龙刀例程包里面就有
https://www.stcaimcu.com/plugin.php?id=mdown:index#/~cateid=8&key=
页: [1]
查看完整版本: 冲哥 子午鸳鸯钺 CAN测试救助