[DAY 18] _UART传输

这是算是大家最常见串列通讯,他原理较简单方便,现在韧体工程师在除错或为简单验证资料,大家知道TX、RX主机和从机对接transmitter(TX)为发射端、receiver(RX)为接收端。
再来我介绍一下协议的部分吧,TX对接另个设备的RX只要两边的设定的鲍率相同就可以做沟通,这设定鲍率就类似像I2C的时脉线,那UART就只剩下资料线而已,那数据的格式就很简单了啦,有点类似I2C。
资料格式:
https://ithelp.ithome.com.tw/upload/images/20211001/20141979BOiZYRZ71T.png
校验位的话可有可无,担心传输中会有偏差造成资料错误,可以选择校验位开启。

STM32的UASRT是同步非同步收发,UART为非同步收发
UASRT可以全双工的Data,UART就去掉同步,我们通常都用到UART而已
UART部分就没这麽复杂了,来看看程序吧

"bsp_uart.h"

#ifndef __BSP_UART_H
#define __BSP_UART_H

#include "stm32f0xx.h"
#include "stdio.h"
#define DEBUG_USARTx                    USART2 
#define DEBUG_USART_CLK                 RCC_APB1Periph_USART2
#define DEBUG_USART_APBxClkCmd          RCC_APB1PeriphClockCmd
#define DEBUG_USART_BAUDRATE            9600

#define DEBUG_USART_GPIO_CLK            RCC_AHBPeriph_GPIOA
#define DEBUG_USART_GPIO_AHBClkCmd      RCC_AHBPeriphClockCmd

#define DEBUG_USART_TX_GPIO_PORT        GPIOA
#define DEBUG_USART_TX_GPIO_PIN         GPIO_Pin_2
#define DEBUG_USART_RX_GPIO_PORT        GPIOA
#define DEBUG_USART_RX_GPIO_PIN         GPIO_Pin_3

void DEBUG_USART_Config(void);
void Usart_SendString( USART_TypeDef * pUSARTx, char *str);
void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch);

这样定义有个好处,移到其他UART口或着是移到其他型号MCU,只要来这边做修改就好。
DEBUG_USART_Config:这是初始化UART外设IO口
Usart_SendString:发送字串
Usart_SendByte:发送1Byte的资料

"bsp_uart.c"

//bsp board support package
#include "bsp_uart.h"
void DEBUG_USART_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure; 
    
	DEBUG_USART_GPIO_AHBClkCmd(DEBUG_USART_GPIO_CLK,ENABLE);
	DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK,ENABLE);

	GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_GPIO_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; 
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_1;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_Init(GPIOA,&GPIO_InitStructure);
	
    GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_GPIO_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource2,GPIO_AF_1);
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource3,GPIO_AF_1);   
	
	USART_InitStructure.USART_BaudRate = DEBUG_USART_BAUDRATE;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_Parity = USART_Parity_No;
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_Init(DEBUG_USARTx,&USART_InitStructure);

	UART_NVIC_InitConfig();
	USART_ITConfig(DEBUG_USARTx,USART_IT_RXNE,ENABLE);
    
    USART_ClearFlag(DEBUG_USARTx,USART_FLAG_TC);
	USART_Cmd(DEBUG_USARTx,ENABLE);
}

可以看到上面,要先开UART的脚位的GPIO口复用功能,复用功能ST都设计好了,你只需要设定到复用功能AF多少就好了。
https://ithelp.ithome.com.tw/upload/images/20211001/20141979SzfUJzA7hT.png
我这边是用PA2、PA3,所以复用AF1(红框部分)

再来是发送的程序:

void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch)
{
  USART_SendData(pUSARTx,ch);
  while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);	
}
void Usart_SendString( USART_TypeDef * pUSARTx, char *str)
{
  unsigned int k=0;
  do 
  {
    Usart_SendByte( pUSARTx, *(str + k) );
    k++;
  } while(*(str + k)!='\0');
  while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET)
  {}
}

int fputc(int ch, FILE *f)
{
	/* 发送一个字节数据到串口 */
	USART_SendData(DEBUG_USARTx, (uint8_t) ch);
	/* 等待传送完毕 */
	while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TXE) == RESET);		
	return (ch);
}
///重定向c库函数scanf到串口可使用scanf、getchar等函数
int fgetc(FILE *f)
{
	/* 等待串口输入数据 */
	while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_RXNE) == RESET);
	return (int)USART_ReceiveData(DEBUG_USARTx);
}

看到int fputc跟int fgetc,这两个函式就是可以让UART传送利用Printf做使用,接收用scanf,这样看起来比较亲切一点。
接下就在主程序就打printf TX就会发送啦,可以快速验证自己的程序有没有符合自己的预期~


<<:  30天打造品牌特色电商网站 Day.17 微互动设计按钮实作(3)

>>:  Day 16 To Do List - 切版 1

[Day1] 专案建置与视窗生成

又到了一年一度的铁人赛啦~?!今年决定尝试用C与OpenGL写出一个2D平台卷轴游戏,希望至少一可以...

Django #2 专案:新增 与 启动

Syntax: django-admin help 1.新增专案 1-1 PyCharm 1-2 ...

8.unity角色移动(刚体Rigidbody2D)

刚体2D(Rigidbody 2D) 当物体运动速度远小於光速可被视为理想刚体,可以忽略型变,也就是...

[Refactoring] Chapter 1 Refactoring: A First Example - RPG Game Hunting Mission

本篇同步发布於个人Blog: [Refactoring] Chapter 1 Refactoring...

[Day16]Basically Speaking

上一篇介绍了Prime Gap,Prime number也就是质数的意思,所以这题也是要我们找质数之...