- 打卡等级:常住居民I
- 打卡总天数:78
- 最近打卡:2026-07-21 13:27:09
已绑定手机
版主
- 积分
- 1069
|
54-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.
按一下P32口按键, 主机发送完整一帧数据.
按一下P33口按键, 主机发送帧头并获取从机应答数据(合并成一串完整的帧).
默认传输速率:9600波特率, 用户可自行修改.
下载时, 默认时钟 48MHz (用户可自行修改频率).
******************************************/
#include "..\comm\STC32G144K246.h"
#include "ai_usb.h"
/**************** 用户定义宏 ****************/
#define MAIN_Fosc 48000000UL
#define Baudrate 9600UL
#define Timer0_Reload (65536UL -(MAIN_Fosc / 1000)) //Timer 0 中断频率, 1000次/秒
/**************** 本地引脚定义 **************/
#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[8];
bit B_1ms; //1ms标志
bit B_TX2_Busy; //发送忙标志
bit RX2_TimeOut;
u8 TX2_Cnt; //发送计数
u8 RX2_Cnt; //接收计数
u8 Key1_cnt;
u8 Key2_cnt;
bit Key1_Flag;
bit Key2_Flag;
u8 RX2_Buffer[UART2_BUF_LENGTH]; //接收缓冲
/**************** 本地函数声明 **************/
void LinInit();
void LinSendMsg(u8 lid, u8 *pdat);
void LinSendHeader(u8 lid);
/********************* 主函数 *************************/
void main(void)
{
u8 i;
EAXFR = 1; //扩展寄存器(XFR)访问使能
CKCON = 0; //提高访问XRAM速度
P3M1 = 0x00; P3M0 = 0x00; //设置为准双向口
P8M1 = 0x00; P8M0 = 0x20; //设置为准双向口,P8.5推挽输出
P9M1 = 0x00; P9M0 = 0x02; //设置为准双向口,P9.1推挽输出
P3PU = 0x0c; //P3.2, P3.3 开启内部上拉
P8PU = 0x30; //LIN_TX, LIN_RX 脚开启内部上拉
AUXR = 0x80; //Timer0 set as 1T, 16 bits timer auto-reload,
TH0 = (u8)(Timer0_Reload / 256);
TL0 = (u8)(Timer0_Reload % 256);
ET0 = 1; //Timer0 interrupt enable
TR0 = 1; //Tiner0 run
Lin_ID = 0x32;
LinInit();
usb_init();
EA = 1; //打开总中断
NORMAL_MODE();
TX_BUF[0] = 0x81;
TX_BUF[1] = 0x22;
TX_BUF[2] = 0x33;
TX_BUF[3] = 0x44;
TX_BUF[4] = 0x55;
TX_BUF[5] = 0x66;
TX_BUF[6] = 0x77;
TX_BUF[7] = 0x88;
while(1)
{
if(B_1ms) //1ms到
{
B_1ms = 0;
if(!P32)
{
if(!Key1_Flag)
{
Key1_cnt++;
if(Key1_cnt > 50)
{
Key1_Flag = 1;
LinSendMsg(Lin_ID, TX_BUF); //发送一串完整数据
TX_BUF[0]++;
Lin_ID++;
}
}
}
else
{
Key1_cnt = 0;
Key1_Flag = 0;
}
if(!P33)
{
if(!Key2_Flag)
{
Key2_cnt++;
if(Key2_cnt > 50)
{
Key2_Flag = 1;
LinSendHeader(0x13); //发送帧头,获取数据帧,组成一个完整的帧
}
}
}
else
{
Key2_cnt = 0;
Key2_Flag = 0;
}
if(RX2_TimeOut) //接收超时
{
RX2_TimeOut = 0;
for(i=0; i<RX2_Cnt; i++) printf_usb("0x%02x ",RX2_Buffer); //从串口输出收到的从机数据
RX2_Cnt = 0; //清除字节数
printf_usb("\r\n");
}
}
if (bUsbOutReady) //USB调试及复位所需代码
{
usb_OUT_done();
}
}
}
/********************** Timer0 1ms中断函数 ************************/
void timer0 (void) interrupt 1
{
B_1ms = 1; //1ms标志
}
//========================================================================
// 函数: 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 SendBreak(void)
// 描述: 主模式发送Lin总线Break函数。
// 参数: none.
// 返回: none.
// 版本: VER1.0
// 日期: 2025-10-28
// 备注:
//========================================================================
void SendBreak(void)
{
USART2CR5 |= 0x04; //主模式 Send Break
LinSendByte(0x00);
}
//========================================================================
// 函数: void LinSendPID(u8 id)
// 描述: ID码加上校验符,转成PID码并发送。
// 参数: ID码.
// 返回: none.
// 版本: VER1.0
// 日期: 2025-10-2
// 备注:
//========================================================================
void LinSendPID(u8 id)
{
u8 P0 ;
u8 P1 ;
P0 = (((id)^(id>>1)^(id>>2)^(id>>4))&0x01)<<6 ;
P1 = ((~((id>>1)^(id>>3)^(id>>4)^(id>>5)))&0x01)<<7 ;
LinSendByte(id|P0|P1);
}
//========================================================================
// 函数: 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 LinSendHeader(u8 lid)
// 描述: Lin主机发送帧头函数。
// 参数: ID码.
// 返回: none.
// 版本: VER1.0
// 日期: 2025-10-28
// 备注:
//========================================================================
void LinSendHeader(u8 lid)
{
SendBreak(); //Send Break
LinSendByte(0x55); //Send Sync Field
LinSendPID(lid); //设置总线ID
}
//========================================================================
// 函数: void LinSendMsg(u8 lid, u8 *pdat)
// 描述: Lin主机发送完整帧函数。
// 参数: lid: Lin ID; *pdat: 发送数据缓冲区.
// 返回: none.
// 版本: VER1.0
// 日期: 2025-10-28
// 备注:
//========================================================================
void LinSendMsg(u8 lid, u8 *pdat)
{
SendBreak(); //Send Break
LinSendByte(0x55); //Send Sync Field
LinSendPID(lid); //设置总线ID
LinSendData(pdat);
LINSendChecksum(pdat);
}
//========================================================================
// 函数: 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[1]
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 Master Mode
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
{
if(S2RI)
{
S2RI = 0; //Clear Rx flag
if(RX2_Cnt >= UART2_BUF_LENGTH) RX2_Cnt = 0;
RX2_Buffer[RX2_Cnt] = S2BUF;
RX2_Cnt++;
}
if(S2TI)
{
S2TI = 0; //Clear Tx flag
B_TX2_Busy = 0;
}
if(UR2TOSR & 0x01)
{
RX2_TimeOut = 1;
UR2TOSR = 0x80; //设置 RTOCF 清除超时标志位 TOIF
}
}
54-LIN总线主机收发测试-USART2.zip
(38.17 KB, 下载次数: 0)
|
|