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_INT
    PieVectTable.LINA_1_INT = &level1ISR; //TX_INT
    PieCtrlRegs.PIEIER8.bit.INTx9 = 1;    //8.9
    PieCtrlRegs.PIEIER8.bit.INTx10 = 1;   //8.10
    IER |= M_INT8;

    GpioCtrlRegs.GPBPUD.bit.GPIO54 = 0;    //Enable pull-up
    GpioCtrlRegs.GPBPUD.bit.GPIO55 = 0;
    //GpioCtrlRegs.GPBQSEL2.bit.GPIO55 = 3;  //Asynch input (LIN_SCI RX)

    GpioCtrlRegs.GPBMUX2.bit.GPIO55 = 2;   // Configure GPIO55 for RX operation
    GpioCtrlRegs.GPBGMUX2.bit.GPIO55 = 2;

    GpioCtrlRegs.GPBMUX2.bit.GPIO54 = 2;   // Configure GPIO54 for TX operation
    GpioCtrlRegs.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 00
    LinaRegs.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];//最大长度128
    va_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_INT
    PieVectTable.LINA_1_INT = &level1ISR; //TX_INT
    PieCtrlRegs.PIEIER8.bit.INTx9 = 1;    //8.9
    PieCtrlRegs.PIEIER8.bit.INTx10 = 1;   //8.10
    IER |= M_INT8;

    GpioCtrlRegs.GPBPUD.bit.GPIO54 = 0;    //Enable pull-up
    GpioCtrlRegs.GPBPUD.bit.GPIO55 = 0;
    //GpioCtrlRegs.GPBQSEL2.bit.GPIO55 = 3;  //Asynch input (LIN_SCI RX)
    GpioCtrlRegs.GPBMUX2.bit.GPIO55 = 2;   // Configure GPIO55 for RX operation
    GpioCtrlRegs.GPBGMUX2.bit.GPIO55 = 2;
    GpioCtrlRegs.GPBMUX2.bit.GPIO54 = 2;   // Configure GPIO54 for TX operation
    GpioCtrlRegs.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 00
    LinaRegs.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];//最大长度1128
    va_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.youkuaiyun.com/download/qq_64257614/90631813

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NULL指向我

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值