STM32——USART串口
文章目录
一、通信接口
二、串口通信
三、硬件电路
四、电平标准
五、串口参数及时序
串口发送数据的数据帧
六、STM32的USART外设简介
七、USART框图
数据的流动
工作原理
增强功能介绍
八、USART基本结构
引脚的模式
九、数据帧
十、起始位侦测和采样位置对齐
十一、数据采样
十二、波特率发生器
十三、数据模式
十四、串口发送
电路设计
关键代码
代码 |
serial.c #include "stm32f10x.h" // Device header #include <stdio.h> #include <stdarg.h>
void Serial_Init(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//推挽复用输出 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure);
USART_InitTypeDef USART_InitStructure; USART_InitStructure.USART_BaudRate = 9600;//设置波特率 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制 USART_InitStructure.USART_Mode = USART_Mode_Tx;//配置收发模式 USART_InitStructure.USART_Parity = USART_Parity_No;//无校验位 USART_InitStructure.USART_StopBits = USART_StopBits_1;//设置停止位 USART_InitStructure.USART_WordLength = USART_WordLength_8b;//设置数据位 USART_Init(USART1, &USART_InitStructure);
USART_Cmd(USART1, ENABLE); } //发送一个字节数据 void Serial_SendByte(uint8_t Byte) { USART_SendData(USART1, Byte);//调用该函数,Byte变量会写入到TDR while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);//等待数据从DR寄存器到移位寄存器,TXE标志位会置1,无须手动清零,在对USART_DR写操作时会将该位清零 } //发送一个数组 void Serial_SendArray(uint8_t *Array, uint16_t Length) { uint16_t i; for (i = 0; i < Length; i ++) { Serial_SendByte(Array[i]); } } //发送一个字符串 void Serial_SendString(char *String) { uint8_t i; //空字符0的转义形式就是'\0' //在ASCLL中一个字符占一个字节 for (i = 0; String[i] != '\0'; i ++) { Serial_SendByte(String[i]); } }
/* 需要拆分数字,以十进制形式拆开 12345/10000%10=1 123456/1000%10=2
数字/10*x%10=某一位 写次方函数返回x的y次方 */
//次方函数,返回值为x的y次方 uint32_t Serial_Pow(uint32_t X, uint32_t Y) { uint32_t Result = 1; while (Y --) { Result *= X; } return Result; }
//发送数字 void Serial_SendNumber(uint32_t Number, uint8_t Length) { uint8_t i; for (i = 0; i < Length; i ++) { Serial_SendByte(Number / Serial_Pow(10, Length - i - 1) % 10 + '0'); //从高位到低位依次发送,以字符的形式发送要加偏移0x30即'0' } } } //printf()的重定向 int fputc(int ch, FILE *f) { Serial_SendByte(ch); return ch; } //方法三:封装sprintf /* sprintf支持可变参数,在封装的时候要注意 引入头文件#include <stdarg.h>
*/ void Serial_Printf(char *format, ...)//...接收可变参数列表 { char String[100]; va_list arg;//定义一个参数列表变量va_list 类型名,arg变量名 va_start(arg, format);//从format位置开始接收参数表,放在arg里面 vsprintf(String, format, arg); va_end(arg);//释放参数表 Serial_SendString(String); }
|
代码 |
main.c #include "stm32f10x.h" // Device header #include "Delay.h" #include "OLED.h" #include "Serial.h"
int main(void) { OLED_Init();
Serial_Init();
Serial_SendByte(0x41);
uint8_t MyArray[] = {0x42, 0x43, 0x44, 0x45}; Serial_SendArray(MyArray, 4);
Serial_SendString("\r\nNum1=");
Serial_SendNumber(111, 3); //printf重定向方法一 printf("\r\nNum2=%d", 222);
//printf重定向方法二:不涉及重定向,适用于多个串口都使用printf char String[100];//定义接收格式化字符串的位置 sprintf(String, "\r\nNum3=%d", 333);//sprintf是格式化输出,第一个参数是指定格式化打印的位置 Serial_SendString(String);
//printf重定向方法三:封装sprintf Serial_Printf("\r\nNum4=%d", 444); Serial_Printf("\r\n");
while (1) {
} } |
USART_SendData()函数
该函数的作用是向DR寄存器发送一个字节的数据
void USART_SendData(USART_TypeDef* USARTx, uint16_t Data)
{
/* Check the parameters */
assert_param(IS_USART_ALL_PERIPH(USARTx));
assert_param(IS_USART_DATA(Data));
/* Transmit Data */
USARTx->DR = (Data & (uint16_t)0x01FF);//与运算将高位清零
}
方法一:printf函数的移植
显示汉字不乱码
采用UTF-8编码
采用GB2312编码
十五、串口发送+接收(只支持一个字节的接收)
电路设计
关键代码
串口接收可以采用查询和中断两种,查询方法是在main函数中查找标志位并读取数据,采用中断方式也是RXNE标志位置1然后会发起中断,需要打开中断通道和写中断响应函数
serial.c
#include "stm32f10x.h" // Device head