当前位置: 首页 > news >正文

TMS320F28P550SJ9学习笔记17:Lin通信SCI模式完整的收发配置

今日初步认识与配置使用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

相关文章:

  • 【实测案例】分布式光纤嵌入U型复材无损强度检测
  • Windows系统安装RustDesk Server的详细步骤和客户端设置
  • 车载诊断架构 --- 车载诊断概念的深度解读
  • Thin-Agent服务(TAS)概述
  • 无头开发模式
  • Vue接口平台学习九——接口用例页面1
  • 15-算法打卡-哈希表-有效的字母异位词-leetcode(242)-第十五天
  • 通信安全员历年考试重难点有哪些?
  • 从0开始掌握动态规划
  • 跟康师傅学Java-面向对象(基础)
  • 秒杀系统解决两个核心问题的思路方法总结:1.库存超卖问题;2.用户重复抢购问题。
  • linux 内核 container_of 宏的原理
  • 批量上传OpenStack镜像
  • python中参数前**的含义
  • 数据结构-前缀树
  • 【Vue 2中的emits声明与Vue 3的defineModel宏函数详解】
  • 蓝牙网关的功能与应用场景
  • Doris的向量化执行如何支撑分布式架构和复杂查询
  • 深度剖析:生成式人工智能备案和登记的关键差异
  • 【HFP】深入解析蓝牙 HFP 协议中呼叫转移、呼叫建立及保持呼叫状态的机制
  • 零食连锁鸣鸣很忙递表港交所:去年营收393亿元,门店超1.4万家,净利润率2.1%
  • 邮储银行一季度净赚超252亿降逾2%,营收微降
  • 外交部官方公众号发布视频:不跪!
  • 美航母一战机坠海,美媒:为躲避胡塞武装攻击,损失超六千万美元
  • 在循环往复的拍摄中,重新发现世界
  • 华侨城A:一季度营收53.63亿元,净利润亏损14.19亿元