DSP 串口通信
DSP串口介绍
串口通信接口(SCI)是一个双线异步串行端口,即通常所说的UART。F28335有3各SCI接口模块。
通信引脚:
SCITXD:SCI发送引脚
SCIRXD:SCI接收引脚
DSP串口配置
初始化模块
void SCIa_Init(Uint32 baud)
{
unsigned char scihbaud=0;
unsigned char scilbaud=0;
Uint16 scibaud=0;
scibaud = 37500000/(8*baud)-1;
scihbaud = scibaud>>8;
scilbaud = scibaud&0xff;
//第一步. 使能 SCI 外设时钟及初始化对应 GPIO ----------------
EALLOW;
SysCtrlRegs.PCLKCR0.bit.SCIAENCLK = 1; // 使能SCI-A时钟
EDIS;
//SCI 的 GPIO 初始化配置,TI 已经在库文件内提供给我们了
//使用哪个 SCI 口可通过宏定义决定,该宏定义在 DSP2833x_Device.h 头文件内已定义了,
//使用哪个就将宏值改为 1 即可
InitSciaGpio();//初始化串口A对应的引脚
//------------------------------------------------------
//第二步.SCI 工作方式及参数设置,包括数据格式、波特率、使能发送、接收功能等。
//Initalize the SCI FIFO
SciaRegs.SCIFFTX.all=0xE040;// FIFO功能使能、重新使能发送FIFO、清除TXFFINT标志位
SciaRegs.SCIFFRX.all=0x204f;//重新使能接收FIFO、清除RXFFINT标志位、接收FIFO深度设置为16
SciaRegs.SCIFFCT.all=0x0;//波特率非自动检测
// Note: Clocks were turned on to the SCIA peripheral
// in the InitSysCtrl() function
SciaRegs.SCICCR.all =0x0007; // 1 stop bit, No loopback
// No parity,8 char bits,
// async mode, idle-line protocol
SciaRegs.SCICTL1.all =0x0003; // enable TX, RX, internal SCICLK,
// Disable RX ERR, SLEEP, TXWAKE
SciaRegs.SCICTL2.all =0x0003;
SciaRegs.SCICTL2.bit.TXINTENA =1; //使能TXRDY中断
SciaRegs.SCICTL2.bit.RXBKINTENA =1; //使能RXRDY、BRKDT中断
SciaRegs.SCIHBAUD = scihbaud ;
SciaRegs.SCILBAUD = scilbaud ;
//SciaRegs.SCICCR.bit.LOOPBKENA =1; // Enable loop back
SciaRegs.SCICTL1.all =0x0023; // Relinquish SCI from Reset,发送使能、接收使能
}
配置串口发送中断:
interrupt void sciaTx_isr()
{
PieCtrlRegs.PIEACK.all |=M_INT9; //发起PIE应答
}
配置串口接收中断:
interrupt void sciaRx_isr()
{
Data = sci_reconechar();
PieCtrlRegs.PIEACK.all |= M_INT9;
}
串口发送字符串
发送单个字符
void SCIa_SendByte(int a)
{
while (SciaRegs.SCICTL2.bit.TXRDY == 0); //等待,直到SCITXDBUF可以接收下一个数据
SciaRegs.SCITXBUF=a;
}
发送字符串
void SCIa_SendString(char * msg)
{
int i=1;
SciaRegs.SCICTL2.bit.TXINTENA = 0;//关闭发送中断
SCIa_SendByte(msg[0]);
while(msg[i] != '\0')
{
SCIa_SendByte(msg[i]);
i++;
}
SciaRegs.SCICTL2.bit.TXINTENA = 1;//发送完成从新开启中断
}
串口发送浮点数
浮点数发送
DSP浮点数的长度为32位因此需要把浮点数拆成4个8位的数来进行发送。
void SCI_Sendfloat(float32 my_float)
{
int32 *ptr;
while (SciaRegs.SCICTL2.bit.TXRDY == 0); //等待,直到SCITXDBUF可以接收下一个数据
SciaRegs.SCICTL2.bit.TXINTENA = 0;//关闭发送中断
ptr = & my_float;
//先发高位再发低位
// SciaRegs.SCITXBUF = *(ptr) >> 24 ;
// SciaRegs.SCITXBUF = *(ptr) >> 16 ;
// SciaRegs.SCITXBUF = *(ptr) >> 8;
// SciaRegs.SCITXBUF = *(ptr);
//先发低位再发高位
SciaRegs.SCITXBUF = *(ptr);
SciaRegs.SCITXBUF = *(ptr) >> 8;
SciaRegs.SCITXBUF = *(ptr) >> 16 ;
SciaRegs.SCITXBUF = *(ptr) >> 24 ;
SciaRegs.SCICTL2.bit.TXINTENA = 1;//发送完成从新开启中断
}
上位机接收
使用的上位机是VOFA,根据VOFA的数据引擎JustFloat的要求传输浮点数需要配置数据包的尾帧。
void Send_tail(void)
{
while (SciaRegs.SCICTL2.bit.TXRDY == 0); //等待,直到SCITXDBUF可以接收下一个数据
SciaRegs.SCICTL2.bit.TXINTENA = 0;//关闭发送中断
//发送数据尾帧
SciaRegs.SCITXBUF = 0x00;
SciaRegs.SCITXBUF = 0x00;
SciaRegs.SCITXBUF = 0x80;
SciaRegs.SCITXBUF = 0x7f;
SciaRegs.SCICTL2.bit.TXINTENA = 1;//发送完成从新开启中断
}
在上位机VOFA中绘制通信波形
只需要在你传输的浮点数末尾调用Send_tail函数加上数据尾帧就可以实现数据的发送。
VOFA会以32位为一组对尾帧数据之前的数据进行拆包解析。因此每次发送的数据顺序应该保持一致。
#include "DSP28x_Project.h"
#include "epwm.h"
#include "bsp_ADC.h"
#include "bsp_sci.h"
extern Uint16 Date;
/**
* @brief 主函数
* @parameter 无
* @return_value 无
*/
void main(void)
{
float32 Duty;
float32 I;
float32 V;
int16 i;
/*第一步:初始化系统控制:*/
InitSysCtrl();
/* 清除所有中断 和初始化 PIE 向量表:*/
DINT;// 禁用CPU中断
InitPieCtrl();// 初始化 PIE 控制寄存器到默认状态,默认状态是全部 PIE 中断被禁用和标志位被清除
IER = 0x0000;// 禁用 CPU 中断和清除所有 CPU 中断标志位:
IFR = 0x0000;
InitPieVectTable();// 初始化 PIE 中断向量表
// 中断重映射,注册中断程序入口(用户按需求添加)
// 指定中断向量表ISR地址
EALLOW;
// PieVectTable.EPWM1_INT = &epwm1_isr;
// PieVectTable.EPWM2_INT = &epwm2_isr;
PieVectTable.SCITXINTA = &sciaTx_isr;
PieVectTable.SCIRXINTA = &sciaRx_isr;
EDIS;
/*程序烧录入28335(可选的)*/
#if RUN_TYPE==FLASH_RUN
MemCopy(&RamfuncsLoadStart,&RamfuncsLoadEnd,&RamfuncsRunStart);
InitFlash();
#endif
// Init_Epwm1();
// Init_Epwm2();
// // 使能CPU中断INT3
// IER |= M_INT3;
// // 中断使能
// PieCtrlRegs.PIEIER3.bit.INTx1 = 1; //使能PIE中断EPWM1_INT
// PieCtrlRegs.PIEIER3.bit.INTx2 = 1; //使能PIE中断EPWM2_INT
// // 使能全局中断
// EINT;
// // 使能实时中断
// ERTM;
// for(;;)
// {
// }
SCIa_Init(115200); //初始化波特率为9600
PieCtrlRegs.PIECTRL.bit.ENPIE = 1;//使能PIE块
IER |= M_INT9;//使能PIEINT9 (SCIA SCIB)
PieCtrlRegs.PIEIER9.bit.INTx1 =1;//SCIA_RX_INT
PieCtrlRegs.PIEIER9.bit.INTx2 =1;//SCIA_TX_INT
EINT;//使能全局中断
ERTM;
SCIa_SendByte('L');
SCIa_SendString("Hello\r\n");
while (1)
{
/* code */
//SCIa_SendString("0.056\r\n");
Duty = 4.98;
V = 198.8;
I = 0;
for(i=0;i<5000;i++)
{
I=I+0.05;
SCI_Sendfloat(Duty);
SCI_Sendfloat(V);
SCI_Sendfloat(I);
Send_tail();
DELAY_US(10000);
}
}
}
文件
串口配置.c文件
#include "bsp_sci.h"
/**
* @brief 串口通行
* @端口 SCITXDA---2 SCIRXDA----141
*
*/
/**
* @brief 窜口初始化
*
* @param baud
*/
Uint16 Data;
void SCIa_Init(Uint32 baud)
{
unsigned char scihbaud=0;
unsigned char scilbaud=0;
Uint16 scibaud=0;
scibaud = 37500000/(8*baud)-1;
scihbaud = scibaud>>8;
scilbaud = scibaud&0xff;
//第一步. 使能 SCI 外设时钟及初始化对应 GPIO ----------------
EALLOW;
SysCtrlRegs.PCLKCR0.bit.SCIAENCLK = 1; // 使能SCI-A时钟
EDIS;
//SCI 的 GPIO 初始化配置,TI 已经在库文件内提供给我们了
//使用哪个 SCI 口可通过宏定义决定,该宏定义在 DSP2833x_Device.h 头文件内已定义了,
//使用哪个就将宏值改为 1 即可
InitSciaGpio();//初始化串口A对应的引脚
//------------------------------------------------------
//第二步.SCI 工作方式及参数设置,包括数据格式、波特率、使能发送、接收功能等。
//Initalize the SCI FIFO
SciaRegs.SCIFFTX.all=0xE040;// FIFO功能使能、重新使能发送FIFO、清除TXFFINT标志位
SciaRegs.SCIFFRX.all=0x204f;//重新使能接收FIFO、清除RXFFINT标志位、接收FIFO深度设置为16
SciaRegs.SCIFFCT.all=0x0;//波特率非自动检测
// Note: Clocks were turned on to the SCIA peripheral
// in the InitSysCtrl() function
SciaRegs.SCICCR.all =0x0007; // 1 stop bit, No loopback
// No parity,8 char bits,
// async mode, idle-line protocol
SciaRegs.SCICTL1.all =0x0003; // enable TX, RX, internal SCICLK,
// Disable RX ERR, SLEEP, TXWAKE
SciaRegs.SCICTL2.all =0x0003;
SciaRegs.SCICTL2.bit.TXINTENA =1; //使能TXRDY中断
SciaRegs.SCICTL2.bit.RXBKINTENA =1; //使能RXRDY、BRKDT中断
SciaRegs.SCIHBAUD = scihbaud ;
SciaRegs.SCILBAUD = scilbaud ;
//SciaRegs.SCICCR.bit.LOOPBKENA =1; // Enable loop back
SciaRegs.SCICTL1.all =0x0023; // Relinquish SCI from Reset,发送使能、接收使能
}
/**
* @brief 单数据发送
*
* @param a
*/
// Transmit a character from the SCI'
void SCIa_SendByte(int a)
{
while (SciaRegs.SCICTL2.bit.TXRDY == 0); //等待,直到SCITXDBUF可以接收下一个数据
SciaRegs.SCITXBUF=a;
}
/**
* @brief 字符串发送
*
* @param msg
*/
void SCIa_SendString(char * msg)
{
int i=1;
SciaRegs.SCICTL2.bit.TXINTENA = 0;//关闭发送中断
SCIa_SendByte(msg[0]);
while(msg[i] != '\0')
{
SCIa_SendByte(msg[i]);
i++;
}
SciaRegs.SCICTL2.bit.TXINTENA = 1;//发送完成从新开启中断
}
void SCI_Sendfloat(float32 my_float)
{
int32 *ptr;
while (SciaRegs.SCICTL2.bit.TXRDY == 0); //等待,直到SCITXDBUF可以接收下一个数据
SciaRegs.SCICTL2.bit.TXINTENA = 0;//关闭发送中断
ptr = & my_float;
//先发高位再发低位
// SciaRegs.SCITXBUF = *(ptr) >> 24 ;
// SciaRegs.SCITXBUF = *(ptr) >> 16 ;
// SciaRegs.SCITXBUF = *(ptr) >> 8;
// SciaRegs.SCITXBUF = *(ptr);
//先发低位再发高位
SciaRegs.SCITXBUF = *(ptr);
SciaRegs.SCITXBUF = *(ptr) >> 8;
SciaRegs.SCITXBUF = *(ptr) >> 16 ;
SciaRegs.SCITXBUF = *(ptr) >> 24 ;
SciaRegs.SCICTL2.bit.TXINTENA = 1;//发送完成从新开启中断
}
/**
* @brief 发送数据尾针
*
*/
void Send_tail(void)
{
while (SciaRegs.SCICTL2.bit.TXRDY == 0); //等待,直到SCITXDBUF可以接收下一个数据
SciaRegs.SCICTL2.bit.TXINTENA = 0;//关闭发送中断
//发送数据尾帧
SciaRegs.SCITXBUF = 0x00;
SciaRegs.SCITXBUF = 0x00;
SciaRegs.SCITXBUF = 0x80;
SciaRegs.SCITXBUF = 0x7f;
SciaRegs.SCICTL2.bit.TXINTENA = 1;//发送完成从新开启中断
}
/**
* @brief 储存接收数据
* @return 接收的数据
*/
Uint16 sci_reconechar (void)
{
Uint16 date;
date = SciaRegs.SCIRXBUF.all;
return date;
}
/**
* @brief 发送中断
*
* @param
*
* @date
*
*/
interrupt void sciaTx_isr()
{
PieCtrlRegs.PIEACK.all |=M_INT9; //发起PIE应答
}
/**
* @brief 接收中断
*
* @return interrupt
*/
interrupt void sciaRx_isr()
{
Data = sci_reconechar();
PieCtrlRegs.PIEACK.all |= M_INT9;
}
串口配置头文件.h
#ifndef _BSP_SCI_H_
#define _BSP_SCI_H_
#include "DSP28x_Project.h"
void SCIa_Init(Uint32 baud);
void SCIa_SendByte(int a);
void SCIa_SendString(char * msg);
Uint16 sci_reconechar (void);
void SCI_Sendfloat(float32 my_float);
void Send_tail(void);
interrupt void sciaTx_isr();
interrupt void sciaRx_isr();
#endif
主函数:
#include "DSP28x_Project.h"
#include "epwm.h"
#include "bsp_ADC.h"
#include "bsp_sci.h"
extern Uint16 Date;
/**
* @brief 主函数
* @parameter 无
* @return_value 无
*/
void main(void)
{
float32 Duty;
float32 I;
float32 V;
int16 i;
/*第一步:初始化系统控制:*/
InitSysCtrl();
/* 清除所有中断 和初始化 PIE 向量表:*/
DINT;// 禁用CPU中断
InitPieCtrl();// 初始化 PIE 控制寄存器到默认状态,默认状态是全部 PIE 中断被禁用和标志位被清除
IER = 0x0000;// 禁用 CPU 中断和清除所有 CPU 中断标志位:
IFR = 0x0000;
InitPieVectTable();// 初始化 PIE 中断向量表
// 中断重映射,注册中断程序入口(用户按需求添加)
// 指定中断向量表ISR地址
EALLOW;
// PieVectTable.EPWM1_INT = &epwm1_isr;
// PieVectTable.EPWM2_INT = &epwm2_isr;
PieVectTable.SCITXINTA = &sciaTx_isr;
PieVectTable.SCIRXINTA = &sciaRx_isr;
EDIS;
/*程序烧录入28335(可选的)*/
#if RUN_TYPE==FLASH_RUN
MemCopy(&RamfuncsLoadStart,&RamfuncsLoadEnd,&RamfuncsRunStart);
InitFlash();
#endif
// Init_Epwm1();
// Init_Epwm2();
// // 使能CPU中断INT3
// IER |= M_INT3;
// // 中断使能
// PieCtrlRegs.PIEIER3.bit.INTx1 = 1; //使能PIE中断EPWM1_INT
// PieCtrlRegs.PIEIER3.bit.INTx2 = 1; //使能PIE中断EPWM2_INT
// // 使能全局中断
// EINT;
// // 使能实时中断
// ERTM;
// for(;;)
// {
// }
SCIa_Init(115200); //初始化波特率为9600
PieCtrlRegs.PIECTRL.bit.ENPIE = 1;//使能PIE块
IER |= M_INT9;//使能PIEINT9 (SCIA SCIB)
PieCtrlRegs.PIEIER9.bit.INTx1 =1;//SCIA_RX_INT
PieCtrlRegs.PIEIER9.bit.INTx2 =1;//SCIA_TX_INT
EINT;//使能全局中断
ERTM;
SCIa_SendByte('L');
SCIa_SendString("Hello\r\n");
while (1)
{
/* code */
//SCIa_SendString("0.056\r\n");
Duty = 4.98;
V = 198.8;
I = 0;
for(i=0;i<5000;i++)
{
I=I+0.05;
SCI_Sendfloat(Duty);
SCI_Sendfloat(V);
SCI_Sendfloat(I);
Send_tail();
DELAY_US(10000);
}
}
}
实验波形:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tLenVRFe-1678870337480)(DSP串口通信浮点数.assets/image-20230315165137606.png)]
参考文献: