当前位置:首页 > 公众号精选 > 嵌入式云IOT技术圈
[导读]之前买了一块评估板,也写了相应的评测文章,链接如下: TKM32F499高性能MCU评估板试用之万事开头难,先点个灯来压压惊! 我们在上面这篇文章已经领会了TKM32F499的强大了,接下来进入主题,串口通信实验。 1、TKM32F499通用异步收发器(UART)数据结构及参数描

之前买了一块评估板,也写了相应的评测文章,链接如下:

TKM32F499高性能MCU评估板试用之万事开头难,先点个灯来压压惊!

我们在上面这篇文章已经领会了TKM32F499的强大了,接下来进入主题,串口通信实验。

1、TKM32F499通用异步收发器(UART)数据结构及参数描述

在UART库的头文件里,UART由一个结构体进行维护:

typedef struct
{
//波特率
uint32_t UART_BaudRate;
//数据长度
uint16_t UART_WordLength;
//停止位
uint16_t UART_StopBits;
//校验位
uint16_t UART_Parity;
//模式
uint16_t UART_Mode;
//硬件流控
uint16_t UART_HardwareFlowControl;
} UART_InitTypeDef;

1.1 波特率

波特率是由波特率发生器产生的,这是一个专用16位的,UART波特率寄存器控制16 位自由运转的计数器的计数周期。提供期望的波特率和 Fosc(APB 时钟频率)

X = SPBRG 寄存器值 (1 to 65535)


1.2 数据长度

/** @defgroup UART_Word_Length
* @{
*/
#define UART_WordLength_5b ((uint16_t)0x0000)
#define UART_WordLength_6b ((uint16_t)0x0010)
#define UART_WordLength_7b ((uint16_t)0x0020)
#define UART_WordLength_8b ((uint16_t)0x0030)

一般在工程应用中都是选择UART_WordLength_8b

1.3 停止位

/** @defgroup UART_Stop_Bits
* @{
*/

#define UART_StopBits_1 ((uint16_t)0x0000)
#define UART_StopBits_2 ((uint16_t)0x0004)

#define IS_UART_STOPBITS(STOPBITS) (((STOPBITS) == UART_StopBits_1) || \
((STOPBITS) == UART_StopBits_2))

一般在工程应用中都是选择UART_StopBits_1

1.4 校验位

/** @defgroup UART_Parity
* @{
*/
#define UART_Parity_No ((uint16_t)0x0000)
#define UART_Parity_Even ((uint16_t)0x0003)
#define UART_Parity_Odd ((uint16_t)0x0001)
#define IS_UART_PARITY(PARITY) (((PARITY) == UART_Parity_No) || \
((PARITY) == UART_Parity_Even) || \
((PARITY) == UART_Parity_Odd))

一般在工程应用中都是选择UART_Parity_No(无校验)

1.5 串口模式

/** @defgroup UART_Mode
* @{
*/

#define UART_Mode_Rx ((uint16_t)0x0008)
#define UART_Mode_Tx ((uint16_t)0x0010)
#define IS_UART_MODE(MODE) ((((MODE) & (uint16_t)0xFFE7) == 0x00) && ((MODE) != (uint16_t)0x00))

这个指的是当前串口为可接收还是可发送,可以同时拥有,也可以单个选择,具体根据项目需求制定。

1.6 硬件流控

/** @defgroup UART_Hardware_Flow_Control
* @{
*/
#define UART_HardwareFlowControl_None ((uint16_t)0x0000)

#define IS_UART_HARDWARE_FLOW_CONTROL(CONTROL)\
(((CONTROL) == UART_HardwareFlowControl_None) || \
((CONTROL) == UART_HardwareFlowControl_RTS) || \
((CONTROL) == UART_HardwareFlowControl_CTS) || \
((CONTROL) == UART_HardwareFlowControl_RTS_CTS))

一般工程应用中会直接将这个设置为UART_HardwareFlowControl_None 在HAL_uart.h库文件中提供了一系列操作接口:

void UART_DeInit(UART_TypeDef* UARTx);
void UART_Init(UART_TypeDef* UARTx, UART_InitTypeDef* UART_InitStruct);
void UART_StructInit(UART_InitTypeDef* UART_InitStruct);
void UART_Cmd(UART_TypeDef* UARTx, FunctionalState NewState);
void UART_ITConfig(UART_TypeDef* UARTx, uint16_t UART_IT, FunctionalState NewState);
void UART_DMACmd(UART_TypeDef* UARTx, uint16_t UART_DMAReq, FunctionalState NewState);
void UART_SendData(UART_TypeDef* UARTx, uint16_t Data);
uint16_t UART_ReceiveData(UART_TypeDef* UARTx);
FlagStatus UART_GetFlagStatus(UART_TypeDef* UARTx, uint16_t UART_FLAG);
void UART_ClearFlag(UART_TypeDef* UARTx, uint16_t UART_FLAG);
ITStatus UART_GetITStatus(UART_TypeDef* UARTx, uint16_t UART_IT);
void UART_ClearITPendingBit(UART_TypeDef* UARTx, uint16_t UART_IT);

跟STM32操作类似,我们直接调就完了,不明白的地方直接看数据手册解决!

2、TKM32F499通用异步收发器(UART)使用

使用串口功能之前,还是一样,先确定我这边的需求,我这边需要接收一串以下格式的数据:

序号 信号值 差值\r\n

这个数据是我手上传感器发过来的数据,然后我用TKM32F499进行接收。

1、配置一路串口用于printf输出,这里选择UART4

电路原理图如下:

根据原理图写出以下初始化函数:

/*用于调试打印*/
void Uart4Init(int BaudRate)
{
UART_InitTypeDef UART_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOD, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出
GPIO_Init(GPIOD, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入

GPIO_Init(GPIOD, &GPIO_InitStructure);

GPIO_PinAFConfig(GPIOD, GPIO_Pin_6 | GPIO_Pin_7, GPIO_AF_UART_2345);

RCC_APB2PeriphClockCmd(RCC_APB2Periph_UART4, ENABLE);
UART_InitStructure.UART_BaudRate = BaudRate; //波特率
UART_InitStructure.UART_WordLength = UART_WordLength_8b;//数据位
UART_InitStructure.UART_StopBits = UART_StopBits_1;//停止位
UART_InitStructure.UART_Parity = UART_Parity_No ;
UART_InitStructure.UART_Mode = UART_Mode_Rx | UART_Mode_Tx;//输入输出模式
UART_InitStructure.UART_HardwareFlowControl = UART_HardwareFlowControl_None;
UART_Init(UART4, &UART_InitStructure);
UART_Cmd(UART4, ENABLE); //UART 模块使能

UART_ClearITPendingBit(UART4, 0xff);
}

调试不用增加接收功能,所以不需要写接收回调函数,但需要写一个串口重定向,并把微库勾上才能使用printf。

编写重定向函数:

int fputc(int ch, FILE *f)
{
while((UART4->CSR & 0x1) == 0) {}
UART4->TDR = (u8) ch;
return ch;
}

2、配置一路串口用于接收传感器数据(这里选择接UART1)

电路原理图如下:

实现代码逻辑:

/*用于接收传感器数据*/
void Uart1Init(int BaudRate)
{
UART_InitTypeDef UART_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //uart1_tx pa9
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 推挽复用输出
GPIO_Init(GPIOA, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //uart1_rx pa10
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入

GPIO_Init(GPIOA, &GPIO_InitStructure);

GPIO_PinAFConfig(GPIOA, GPIO_Pin_9 | GPIO_Pin_10, GPIO_AF_UART_1); //PA9、PA10复用为串口1
GPIO_PinAFConfig(GPIOA, GPIO_Pin_15, GPIO_AF_GPIO); //PA15复用为普通GPIO

RCC_APB2PeriphClockCmd(RCC_APB2Periph_UART1, ENABLE);
UART_InitStructure.UART_BaudRate = BaudRate; //波特率
UART_InitStructure.UART_WordLength = UART_WordLength_8b;//数据位
UART_InitStructure.UART_StopBits = UART_StopBits_1;//停止位
UART_InitStructure.UART_Parity = UART_Parity_No ;
UART_InitStructure.UART_Mode = UART_Mode_Rx | UART_Mode_Tx;//输入输出模式
UART_InitStructure.UART_HardwareFlowControl = UART_HardwareFlowControl_None;
UART_Init(UART1, &UART_InitStructure);
UART_Cmd(UART1, ENABLE); //UART 模块使能

UART_ClearITPendingBit(UART1, 0xff);
//这里需要进行接收,所以要打开接收中断
UART_ITConfig(UART1, UART_IT_RXIEN, ENABLE);//使能接收中断
NVIC_SetPriority(UART1_IRQn, 3);
NVIC_EnableIRQ(UART1_IRQn);
}

定义回调函数,编写接收逻辑,传感器用一个结构体进行维护:

#define SENSOR_BUFFER_SIZE       42

typedef struct
{
uint8_t BufferReady;
uint16_t Sensor_rx_count ;
uint8_t SensorRxBuffer[SENSOR_BUFFER_SIZE];
uint8_t SensorTxBuffer[SENSOR_BUFFER_SIZE];
} Sensor_HandleTypeDef;
extern Sensor_HandleTypeDef Sensor;

接收回调函数处理:

//串口1接收中断处理函数,打印传感器数据
void UART1_IRQHandler(void)
{
u8 ucCh;

/*当ISR位1为1时,表示接收到有效字节数据*/
if(UART1->ISR & (1 << 1))
{
/*接收到了一个字节的数据*/
ucCh = UART1->RDR;
if('\n' != ucCh)
{
Sensor.SensorRxBuffer[Sensor.Sensor_rx_count++] = ucCh ;
}
else
{
/*如果接收的是\n,则上一个接收的数据为'\r'结束*/
if('\r' == Sensor.SensorRxBuffer[Sensor.Sensor_rx_count - 1])
{
/*添加结束符*/
Sensor.SensorRxBuffer[Sensor.Sensor_rx_count - 1] = 0x00 ;
/*接收计数清0*/
Sensor.Sensor_rx_count = 0 ;
Sensor.BufferReady = 1 ;
}
}
/*清除中断接收标志*/
UART1->ICR |= 1 << 1;
}
}

接收这里主要用到串口的接收数据寄存器、中断状态寄存器、中断清除寄存器

接收数据在程序里就是一个RDR的寄存器。其中在接收逻辑里需要去判断接收数据有效,最重要的是位1:

在每次收到一次有效数据,即发生了一次串口接收中断,我们接收完数据后需要及时对中断标志进行清除,这里最重要的是第一位:这些寄存器都是通过一个结构体进行维护:

/**
* @brief Universal Synchronous Asynchronous Receiver Transmitter
*/

typedef struct
{
__IO uint32_t TDR;
__IO uint32_t RDR;
__IO uint32_t CSR;
__IO uint32_t ISR;
__IO uint32_t IER;
__IO uint32_t ICR;
__IO uint32_t GCR;
__IO uint32_t CCR;
__IO uint32_t BRR;
__IO uint32_t FRABRG;

} UART_TypeDef;

具体使用方法请参考TKM32F499的芯片数据手册,当然如果不习惯用寄存器进行操作,也可以使用好炬润官方的HAL lib,调用相应的库函数。串口应用逻辑编写完毕以后,接下来我们在主函数的循环内判断BufferReady标志就可以了:

while(1)
{
if(1 == Sensor.BufferReady)
{
Sensor.BufferReady = 0;
/*解析传感器数据*/
Sensor_Detect_Process(Sensor.SensorRxBuffer);
printf("流水号:%d 信号值:%d 差值:%d\n",sensor_data.Sensor_Serial_Number
,sensor_data.Sensor_TP1_Singal_Value,sensor_data.Sensor_TP1_Devalue
);
LCD_PutString(100, 60, (char *)Sensor.SensorRxBuffer, Red, Yellow, 1);
status = !status;
GPIO_WriteBit(GPIOA,GPIO_Pin_15,status);
}
}

最终效果,这里面还有我的其它逻辑:

如果对该评估板软件编程感兴趣的话,欢迎加我微信私聊交流~

TKM32F499评估板例程及资料下载

链接:https://pan.baidu.com/s/1xujEO4vJ7i7UUK7v_fGNgw
提取码:g1y2

或者后台回复TK499即可获取。

往期精彩

bin文件转换为hex文件C语言实现

最近收集的开源项目专栏(持续更新,收好车轮,方便造车)

推荐三个我工作中经常使用的驱动大全wiki(建议收藏并转发让更多人知道!)

变量命名还在谷歌百度翻译?OUT啦!分享一个我日常工作中常用的变量命名神器!

若觉得本次分享的文章对您有帮助,随手点[在看]并转发分享,也是对我的支持。

免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

9月2日消息,不造车的华为或将催生出更大的独角兽公司,随着阿维塔和赛力斯的入局,华为引望愈发显得引人瞩目。

关键字: 阿维塔 塞力斯 华为

加利福尼亚州圣克拉拉县2024年8月30日 /美通社/ -- 数字化转型技术解决方案公司Trianz今天宣布,该公司与Amazon Web Services (AWS)签订了...

关键字: AWS AN BSP 数字化

伦敦2024年8月29日 /美通社/ -- 英国汽车技术公司SODA.Auto推出其旗舰产品SODA V,这是全球首款涵盖汽车工程师从创意到认证的所有需求的工具,可用于创建软件定义汽车。 SODA V工具的开发耗时1.5...

关键字: 汽车 人工智能 智能驱动 BSP

北京2024年8月28日 /美通社/ -- 越来越多用户希望企业业务能7×24不间断运行,同时企业却面临越来越多业务中断的风险,如企业系统复杂性的增加,频繁的功能更新和发布等。如何确保业务连续性,提升韧性,成...

关键字: 亚马逊 解密 控制平面 BSP

8月30日消息,据媒体报道,腾讯和网易近期正在缩减他们对日本游戏市场的投资。

关键字: 腾讯 编码器 CPU

8月28日消息,今天上午,2024中国国际大数据产业博览会开幕式在贵阳举行,华为董事、质量流程IT总裁陶景文发表了演讲。

关键字: 华为 12nm EDA 半导体

8月28日消息,在2024中国国际大数据产业博览会上,华为常务董事、华为云CEO张平安发表演讲称,数字世界的话语权最终是由生态的繁荣决定的。

关键字: 华为 12nm 手机 卫星通信

要点: 有效应对环境变化,经营业绩稳中有升 落实提质增效举措,毛利润率延续升势 战略布局成效显著,战新业务引领增长 以科技创新为引领,提升企业核心竞争力 坚持高质量发展策略,塑强核心竞争优势...

关键字: 通信 BSP 电信运营商 数字经济

北京2024年8月27日 /美通社/ -- 8月21日,由中央广播电视总台与中国电影电视技术学会联合牵头组建的NVI技术创新联盟在BIRTV2024超高清全产业链发展研讨会上宣布正式成立。 活动现场 NVI技术创新联...

关键字: VI 传输协议 音频 BSP

北京2024年8月27日 /美通社/ -- 在8月23日举办的2024年长三角生态绿色一体化发展示范区联合招商会上,软通动力信息技术(集团)股份有限公司(以下简称"软通动力")与长三角投资(上海)有限...

关键字: BSP 信息技术
关闭
关闭