今日初步认识与配置使用Lin通信SCI模式完整的发送与中断接收功能,用结构体寄存器的方式编程
文章提供完整工程下载、测试效果图
我的单片机平台是这个:
目录
LIN-SCI接收中断:
LIN-SCI初始化:
LIN的发送函数:
#include "Lin_1.h"
测试效果图:
完整工程下载:
LIN-SCI接收中断:
手册3459页提到了SCI的接收中断
手册还提到了INT0 与INT1 这俩个LIN通信提供的中断源可以链接各种类型的中断:
在代码中,我将RX中断连接到了INT0上:
其次,INT0 与 INT1 还需要开启 PIE总中断:
LIN-SCI初始化:
接收中断打开了,但注释了发送中断
如果你启用发送中断,需要自己链接到中断服务函数并清理对应标志位!
void Init_LINA_SCIMode(void) {//uint32_t i;// 链接中断服务函数 与 初始化引脚EALLOW;PieVectTable.LINA_0_INT = &level0ISR; //RX_INTPieVectTable.LINA_1_INT = &level1ISR; //TX_INTPieCtrlRegs.PIEIER8.bit.INTx9 = 1; //8.9PieCtrlRegs.PIEIER8.bit.INTx10 = 1; //8.10IER |= M_INT8;GpioCtrlRegs.GPBPUD.bit.GPIO54 = 0; //Enable pull-upGpioCtrlRegs.GPBPUD.bit.GPIO55 = 0;//GpioCtrlRegs.GPBQSEL2.bit.GPIO55 = 3; //Asynch input (LIN_SCI RX)GpioCtrlRegs.GPBMUX2.bit.GPIO55 = 2; // Configure GPIO55 for RX operationGpioCtrlRegs.GPBGMUX2.bit.GPIO55 = 2;GpioCtrlRegs.GPBMUX2.bit.GPIO54 = 2; // Configure GPIO54 for TX operationGpioCtrlRegs.GPBGMUX2.bit.GPIO54 = 2;GpioCtrlRegs.GPBDIR.bit.GPIO54 = 1; // 输出(TX)GpioCtrlRegs.GPBDIR.bit.GPIO55 = 0; // 输入(RX)//此位确定INT1中断行是否产生对PIE的中断LinaRegs.LIN_GLB_INT_EN.bit.GLBINT0_EN = 1;LinaRegs.LIN_GLB_INT_EN.bit.GLBINT1_EN = 1;LinaRegs.SCISETINTLVL.bit.SETRXINTOVO = 0; // 0:中断映射到INT0线 1:中断映射到INT1线//重载 以启用 LIN模块LinaRegs.SCIGCR0.bit.RESET = 1;LinaRegs.SCIGCR1.bit.SWnRST = 0;//引脚控制寄存器LinaRegs.SCIPIO0.bit.RXFUNC = 1;LinaRegs.SCIPIO0.bit.TXFUNC = 1;//SCI兼容模式引脚LinaRegs.SCIPIO2.bit.RXIN = 1;LinaRegs.SCIPIO2.bit.TXIN = 1;//多缓冲区模式:LinaRegs.SCIGCR1.bit.MBUFMODE = 0; //是否使用RX/TX多缓冲器或使用单个寄存器RD0/TD0。LinaRegs.SCIGCR1.bit.STOP = 0; //0:1位停止位 1:2位停止位LinaRegs.SCIGCR1.bit.PARITYENA = 0; // 禁用奇偶校验LinaRegs.SCIGCR1.bit.PARITY = 0; //0:奇校验 1::偶校验 (如果使能了奇偶校验)LinaRegs.SCIFORMAT.bit.CHAR = 7; //8位数据长度//设定 波特率 115200 得到组合: P=39 M=11 U=0 ---> VCLK 默认 SYSCLK 2分频// ClkCfgRegs.PERCLKDIVSEL.bit.LINACLKDIV = 4; // 预分频 VCLK = SYSCLK / 4 = 375 000 00LinaRegs.BRSR.bit.M = 11;LinaRegs.BRSR.bit.SCI_LIN_PSH = (39 >> 8) & 0xff;LinaRegs.BRSR.bit.SCI_LIN_PSL = 39 & 0xff;LinaRegs.BRSR.bit.U = 0;LinaRegs.SCIGCR1.bit.CLK_COMMANDER = 1; //SCI兼容模式LinaRegs.SCIGCR1.bit.TIMINGMODE = 1; //SCI异步操作,SCI模式必须设为1 // LinaRegs.SCIGCR1.bit.COMMMODE = 0;//0:SCI空闲线 1:SCI地址位LinaRegs.SCIGCR1.bit.ADAPT = 0; //禁用自动波特率LinaRegs.SCIGCR1.bit.CONT = 1; //使LIN在仿真断点处不会停止,直到LIN当前接收或传输完成//使能收发LinaRegs.SCIGCR1.bit.RXENA = 1;LinaRegs.SCIGCR1.bit.TXENA = 1;//使能中断LinaRegs.SCISETINT.bit.SETRXINT = 1; //接收中断//LinaRegs.SCISETINT.bit.SETTXINT = 1; //发送中断//重启LIN模块LinaRegs.SCIGCR1.bit.SWnRST = 1;EDIS; }
LIN的发送函数:
我写了三个发送函数,分别是单个字节发送,字符串发送,printf,
最后一个适合调试,用法如下:
void LIN_Transmit_Data_SCIMode(unsigned char Data) {LinaRegs.SCITD.bit.TD = Data;while (LinaRegs.SCIFLR.bit.TXRDY == 0) //等待发送完成{//考虑添加超时逻辑} // LinaRegs.SCIFLR.bit.TXEMPTY // LinaRegs.SCIFLR.bit.TXRDY }void LIN_Transmit_String_SCIMode(unsigned char *string) {int i;i = 0;while(string[i] != '\0'){LIN_Transmit_Data_SCIMode(string[i]);i++;} }// 自定义printf函数 void LIN_SCIMode_Printf(char *fmt,...) {unsigned char UsartPrintfBuf[128];//最大长度128va_list ap;unsigned char *pStr = UsartPrintfBuf;va_start(ap, fmt);vsnprintf((char *)UsartPrintfBuf, sizeof(UsartPrintfBuf), fmt, ap); //格式化va_end(ap);while(*pStr != 0 ){LIN_Transmit_Data_SCIMode(*pStr++); //逐个字节发送// 检查传输错误} }
#include "Lin_1.h"
完整的LIN通信配置代码如下:
/** Lin.c** Created on: 2025年4月11日* Author: 30313*/ #include "Lin_1.h"void Init_LINA_SCIMode(void) {//uint32_t i;// 链接中断服务函数 与 初始化引脚EALLOW;PieVectTable.LINA_0_INT = &level0ISR; //RX_INTPieVectTable.LINA_1_INT = &level1ISR; //TX_INTPieCtrlRegs.PIEIER8.bit.INTx9 = 1; //8.9PieCtrlRegs.PIEIER8.bit.INTx10 = 1; //8.10IER |= M_INT8;GpioCtrlRegs.GPBPUD.bit.GPIO54 = 0; //Enable pull-upGpioCtrlRegs.GPBPUD.bit.GPIO55 = 0;//GpioCtrlRegs.GPBQSEL2.bit.GPIO55 = 3; //Asynch input (LIN_SCI RX)GpioCtrlRegs.GPBMUX2.bit.GPIO55 = 2; // Configure GPIO55 for RX operationGpioCtrlRegs.GPBGMUX2.bit.GPIO55 = 2;GpioCtrlRegs.GPBMUX2.bit.GPIO54 = 2; // Configure GPIO54 for TX operationGpioCtrlRegs.GPBGMUX2.bit.GPIO54 = 2;GpioCtrlRegs.GPBDIR.bit.GPIO54 = 1; // 输出(TX)GpioCtrlRegs.GPBDIR.bit.GPIO55 = 0; // 输入(RX)//重载 以启用 LIN模块LinaRegs.SCIGCR0.bit.RESET = 1;LinaRegs.SCIGCR1.bit.SWnRST = 0;//引脚控制寄存器LinaRegs.SCIPIO0.bit.RXFUNC = 1;LinaRegs.SCIPIO0.bit.TXFUNC = 1;//SCI兼容模式引脚LinaRegs.SCIPIO2.bit.RXIN = 1;LinaRegs.SCIPIO2.bit.TXIN = 1;//多缓冲区模式:LinaRegs.SCIGCR1.bit.MBUFMODE = 0; //是否使用RX/TX多缓冲器或使用单个寄存器RD0/TD0。LinaRegs.SCIGCR1.bit.STOP = 0; //0:1位停止位 1:2位停止位LinaRegs.SCIGCR1.bit.PARITYENA = 0; // 禁用奇偶校验LinaRegs.SCIGCR1.bit.PARITY = 0; //0:奇校验 1::偶校验 (如果使能了奇偶校验)LinaRegs.SCIFORMAT.bit.CHAR = 7; //8位数据长度//设定 波特率 115200 得到组合: P=39 M=11 U=0 ---> VCLK 默认 SYSCLK 2分频// ClkCfgRegs.PERCLKDIVSEL.bit.LINACLKDIV = 4; // 预分频 VCLK = SYSCLK / 4 = 375 000 00LinaRegs.BRSR.bit.M = 11;LinaRegs.BRSR.bit.SCI_LIN_PSH = (39 >> 8) & 0xff;LinaRegs.BRSR.bit.SCI_LIN_PSL = 39 & 0xff;LinaRegs.BRSR.bit.U = 0;LinaRegs.SCIGCR1.bit.CLK_COMMANDER = 1; //SCI兼容模式LinaRegs.SCIGCR1.bit.TIMINGMODE = 1; //SCI异步操作,SCI模式必须设为1 // LinaRegs.SCIGCR1.bit.COMMMODE = 0;//0:SCI空闲线 1:SCI地址位LinaRegs.SCIGCR1.bit.ADAPT = 0; //禁用自动波特率LinaRegs.SCIGCR1.bit.CONT = 1; //使LIN在仿真断点处不会停止,直到LIN当前接收或传输完成//使能收发LinaRegs.SCIGCR1.bit.RXENA = 1;LinaRegs.SCIGCR1.bit.TXENA = 1;//此位确定INT1中断行是否产生对PIE的中断LinaRegs.LIN_GLB_INT_EN.bit.GLBINT0_EN = 1;LinaRegs.LIN_GLB_INT_EN.bit.GLBINT1_EN = 1;LinaRegs.SCISETINTLVL.bit.SETRXINTOVO = 0; // 0:中断映射到INT0线 1:中断映射到INT1线//使能中断LinaRegs.SCISETINT.bit.SETRXINT = 1; //接收中断//LinaRegs.SCISETINT.bit.SETTXINT = 1; //发送中断//重启LIN模块LinaRegs.SCIGCR1.bit.SWnRST = 1;EDIS; }// 会有其余中断情况 会进这个函数 // 我只是连接了RX 中断 与 INT0 的关系 __interrupt void level0ISR(void) {unsigned char temp;static unsigned char i = 0;//记录进了几次中断,查看是否有除了RX中断的中断i++;//如果接收中断if(LinaRegs.SCIFLR.bit.RXRDY == 1){temp = LinaRegs.SCIRD.bit.RD;//不读RXRDY不会清除,RXRDY写1才能清除LIN_Transmit_Data_SCIMode(temp);}LinaRegs.LIN_GLB_INT_CLR.bit.INT0_FLG_CLR = 1;//清除中断PieCtrlRegs.PIEACK.all = PIEACK_GROUP8;//LinaRegs.SCICLEARINT.bit.CLRRXINT = 1;//关闭接收中断//LinaRegs.SCISETINT.bit.SETRXINT = 1; //重新启用接收中断 }__interrupt void level1ISR(void) {}void LIN_Transmit_Data_SCIMode(unsigned char Data) {LinaRegs.SCITD.bit.TD = Data;while (LinaRegs.SCIFLR.bit.TXRDY == 0) //等待发送完成{//考虑添加超时逻辑} // LinaRegs.SCIFLR.bit.TXEMPTY // LinaRegs.SCIFLR.bit.TXRDY }void LIN_Transmit_String_SCIMode(unsigned char *string) {int i;i = 0;while(string[i] != '\0'){LIN_Transmit_Data_SCIMode(string[i]);i++;} }// 自定义printf函数 void LIN_SCIMode_Printf(char *fmt,...) {unsigned char UsartPrintfBuf[128];//最大长度1128va_list ap;unsigned char *pStr = UsartPrintfBuf;va_start(ap, fmt);vsnprintf((char *)UsartPrintfBuf, sizeof(UsartPrintfBuf), fmt, ap); //格式化va_end(ap);while(*pStr != 0 ){LIN_Transmit_Data_SCIMode(*pStr++); //逐个字节发送// 检查传输错误} }
/** Lin.h** Created on: 2025年4月11日* Author: 30313*/#ifndef USER_LIN_1_H_ #define USER_LIN_1_H_//#include "stdint.h" //uint32_t /uint16_t #include "f28x_project.h" #include "f28p55x_epwm_defines.h"#include "stdio.h" #include "stdarg.h"__interrupt void level0ISR(void); __interrupt void level1ISR(void); void Init_LINA_SCIMode(void); void LIN_Transmit_Data_SCIMode(unsigned char Data); void LIN_Transmit_String_SCIMode(unsigned char *string); void LIN_SCIMode_Printf(char *fmt,...);#endif /* USER_LIN_1_H_ */
测试效果图:
程序自动循环发送数据的同时,接收到消息会立刻回传:
完整工程下载:
https://download.csdn.net/download/qq_64257614/90631813