芯启元 发表于 2026-7-3 14:29:39

53-LIN总线从机收发测试-USART2,STC32G144K246实验箱演示程序

53-LIN总线从机收发测试-USART2,STC32G144K246实验箱演示程序
主程序main.C代码如下(汇编版本在附件中):


/*---------------------------------------------------------------------*/
/* --- Web: www.STCAI.com ---------------------------------------------*/
/* --- BBS: www.STCAIMCU.com-----------------------------------------*/
/*---------------------------------------------------------------------*/

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

本例程基于STC32G144K246为主控芯片的实验箱进行编写测试。

使用Keil C251编译器,Memory Model推荐设置XSmall模式,默认定义变量在edata,单时钟存取访问速度快。

edata建议保留1K给堆栈使用,空间不够时可将大数组、不常用变量加xdata关键字定义到xdata空间。

USART类型Lin从机总线收发测试用例,默认通信脚:P8.4 P8.5.

收到一个非本机应答的完整帧后通过USB-CDC串口输出, 并保存到数据缓存.

收到一个本机应答的帧头后(例如:ID=0x13), 发送据进行应答.

默认传输速率:9600波特率, 用户可自行修改.

下载时, 默认时钟 48MHz (用户可自行修改频率).

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

#include "..\comm\STC32G144K246.h"
#include "ai_usb.h"

/****************用户定义宏****************/

#define MAIN_Fosc      48000000UL
#define Baudrate         9600UL

/****************本地引脚定义**************/

#define NORMAL_MODE() P9SETB= 0x02//P91 = 1
#define SLEEP_MODE()P9CLRB= 0x02//P91 = 0

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

#define FRAME_LEN         8    //数据长度: 8 字节
#define UART2_BUF_LENGTH    64

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

u8 Lin_ID;
u8 TX_BUF;

bit B_RX2_Flag; //接收标志
bit B_TX2_Busy; //发送忙标志
bit RX2_TimeOut;
u8TX2_Cnt;    //发送计数
u8RX2_Cnt;    //接收计数

u8RX2_Buffer; //接收缓冲

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

void LinInit(void);
void LinStatusRead(void);
void LinSendData(u8 *pdat);
void LINSendChecksum(u8 *dat);

/********************* 主函数 *************************/
void main(void)
{
    u8 i;
   
    EAXFR = 1; //扩展寄存器(XFR)访问使能
    CKCON = 0; //提高访问XRAM速度

    P8M1 = 0x00;   P8M0 = 0x20;   //设置为准双向口,P8.5推挽输出
    P9M1 = 0x00;   P9M0 = 0x02;   //设置为准双向口,P9.1推挽输出

    P8PU = 0x30;    //LIN_TX, LIN_RX 脚开启内部上拉

    Lin_ID = 0x32;
    LinInit();
    usb_init();
    EA = 1;         //打开总中断

    NORMAL_MODE();
    TX_BUF = 0x81;
    TX_BUF = 0x22;
    TX_BUF = 0x33;
    TX_BUF = 0x44;
    TX_BUF = 0x55;
    TX_BUF = 0x66;
    TX_BUF = 0x77;
    TX_BUF = 0x88;
   
    printf_usb("STC32G144K246 USART2 to LIN Test Programme!\r\n");

    while(1)
    {
      if((B_RX2_Flag) && (RX2_Cnt >= 2))
      {
            B_RX2_Flag = 0;

            if((RX2_Buffer == 0x55) && ((RX2_Buffer & 0x3f) == 0x13)) //PID -> ID
            {
                printf_usb("Send response.\r\n");
                LinSendData(TX_BUF);
                LINSendChecksum(TX_BUF);
            }
      }

      if(RX2_TimeOut)   //接收超时
      {
            RX2_TimeOut = 0;

            printf_usb("Read ID = 0x%02X.\r\n",RX2_Buffer&0x3f);
            for(i=2; i<RX2_Cnt; i++)    printf_usb("0x%02x ",RX2_Buffer);//输出收到的数据
            RX2_Cnt= 0;   //清除字节数
            printf_usb("\r\n");
      }

      if (bUsbOutReady)   //USB调试及复位所需代码
      {
            usb_OUT_done();
      }
    }
}

//========================================================================
// 函数: void LinSendByte(u8 dat)
// 描述: 发送一个字节函数。
// 参数: none.
// 返回: none.
// 版本: VER1.0
// 日期: 2025-10-28
// 备注:
//========================================================================
void LinSendByte(u8 dat)
{
    B_TX2_Busy = 1;
    S2BUF = dat;
    while(B_TX2_Busy);
}

//========================================================================
// 函数: u16 LinSendData(u8 *pdat)
// 描述: Lin发送数据函数。
// 参数: *pdat: 设置数据缓冲区.
// 返回: Lin ID.
// 版本: VER1.0
// 日期: 2025-10-28
// 备注:
//========================================================================
void LinSendData(u8 *pdat)
{
    u8 i;

    for(i=0;i<FRAME_LEN;i++)
    {
LinSendByte(pdat);
    }
}

//========================================================================
// 函数: void LINSendChecksum(u8 *dat)
// 描述: 计算校验码并发送。
// 参数: 数据场传输的数据.
// 返回: none.
// 版本: VER1.0
// 日期: 2025-10-2
// 备注:
//========================================================================
void LINSendChecksum(u8 *dat)
{
    u16 sum = 0;
    u8 i;

    for(i = 0; i < FRAME_LEN; i++)
    {
      sum += dat;
      if(sum & 0xFF00)
      {
            sum = (sum & 0x00FF) + 1;
      }
    }
    sum ^= 0x00FF;
    LinSendByte((u8)sum);
}

//========================================================================
// 函数: void LinSetBaudrate(u16 brt)
// 描述: Lin总线波特率设置函数。
// 参数: brt: 波特率.
// 返回: none.
// 版本: VER1.0
// 日期: 2025-10-28
// 备注:
//========================================================================
void LinSetBaudrate(u16 brt)
{
    u16 tmp;
   
    tmp = (MAIN_Fosc >> 4) / brt;
    USART2BRH = (u8)(tmp>>8);
    USART2BRL = (u8)tmp;
}

//========================================================================
// 函数: void LinInit(void)
// 描述: Lin初始化函数。
// 参数: none.
// 返回: none.
// 版本: VER1.0
// 日期: 2025-10-05
// 备注:
//========================================================================
void LinInit(void)
{
    S2_S= 0;      //USART2 switch to: 00: P1.0 P1.1, 01: P4.6 P4.7, 10: P8.4,P8.5, 11: PA.0,PA.1
    P_SWX1 = (P_SWX1 & 0xdf) | 0x20;    //bit5: S2_S

    S2CFG |= 0x01;//使用串口2时,W1位必需设置为1,否则可能会产生不可预期的错误
    S2CON = (S2CON & 0x3f) | 0x50;      //8位数据,可变波特率, 允许接收
    AUXR |= 0x14;   //定时器2时钟1T模式,开始计时
    ES2 = 1;      //允许中断

    LinSetBaudrate(Baudrate);   //设置波特率
    S2CFG |= 0x80;            //S2MOD = 1
    USART2CR1 |= 0x80;          //LIN Mode Enable
    USART2CR5 |= 0x20;          //LIN Slave Mode

    USART2CR5 |= 0x10;          //AutoSync

    UR2TOCR = 0xc0;             //bit7:使能超时接收,bit6:使能超时中断,bit5:超时时钟选择 1:系统时钟0:串口数据位率(波特率)
    UR2TOTL = 0x20;
    UR2TOTH = 0x00;
    UR2TOTE = 0x00;             //需要写 URxTOTE 后,新的TM值才会生效
}

//========================================================================
// 函数: void UART2_int (void) interrupt UART2_VECTOR
// 描述: UART2中断函数。
// 参数: nine.
// 返回: none.
// 版本: VER1.0
// 日期: 2025-10-28
// 备注:
//========================================================================
void UART2_int (void) interrupt 8
{
    u8 Status;

    if(S2RI)
    {
      S2RI = 0;         //Clear Rx flag

      Status = USART2CR5;
      if(Status & 0x02)   //if LIN header is detected
      {
            B_RX2_Flag = 1;
      }

      if(Status & 0xc0)   //if LIN break is detected / LIN header error is detected
      {
            RX2_Cnt = 0;
      }

      RX2_Buffer = S2BUF;
      if(RX2_Cnt >= UART2_BUF_LENGTH)   RX2_Cnt = 0;

      USART2CR5 &= ~0xcb; //Clear flag
    }

    if(S2TI)
    {
      S2TI = 0;         //Clear Tx flag
      B_TX2_Busy = 0;
    }

    if(UR2TOSR & 0x01)
    {
      RX2_TimeOut = 1;
      UR2TOSR = 0x80;   //设置 RTOCF 清除超时标志位 TOIF
    }
}




页: [1]
查看完整版本: 53-LIN总线从机收发测试-USART2,STC32G144K246实验箱演示程序