本文是基于江科大B站视频编写,参考各种资料进行学习。
1、USART串口协议
硬件电路(接线)
2、USART串口外设
常用波特率为9600、115200
必须对应特定引脚,才能实现通信,如果引脚冲突,看看有没有重映射来改变引脚。
fpclk频率是指SPI所在的APB总线频率,APB1为fpclk1,APB2为fpclk2。
3、串口发送程序
(1)接线
为什么选用PA9、10这两个引脚,如下图:
实物:
(2)代码
(a)main.c
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "serial.h"
int main(void)
{
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("\r\nNum2=%d", 222);
char String[100];
sprintf(String, "\r\nNum3=%d", 333);
Serial_SendString(String);
Serial_Printf("\r\nNum4=%d", 444);
Serial_Printf("王哈哈\r\n");
while (1)
{
}
}
(b)serial.c
#include "stm32f4xx.h"
#include "serial.h"
#include <stdio.h>
#include <stdarg.h>
void SERIAL_Init(void)
{
//GPIO端口设置
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //使能GPIOA时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//使能USART1时钟
//串口1对应引脚复用映射
GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1); //GPIOA9复用为USART1
GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1); //GPIOA10复用为USART1
//USART1端口配置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; //GPIOA9与GPIOA10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度50MHz
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA9,PA10
//USART1 初始化设置
USART_InitStructure.USART_BaudRate = bound;//波特率设置
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式
USART_Init(USART1, &USART_InitStructure); //初始化串口1
USART_Cmd(USART1, ENABLE); //使能串口1
}
void Serial_SendByte(uint8_t Byte)
{
USART_SendData(USART1, Byte);
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}
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;
for (i = 0; String[i] != '\0'; i ++)
{
Serial_SendByte(String[i]);
}
}
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');
}
}
int fputc(int ch, FILE *f)//为下面的函数做准备
{
Serial_SendByte(ch);
return ch;
}
void Serial_Printf(char *format, ...)
{
char String[100];
va_list arg;
va_start(arg, format);
vsprintf(String, format, arg);
va_end(arg);
Serial_SendString(String);
}
(c)serial.h
#ifndef __SERIAL_H
#define __SERIAL_H
#include <stdio.h>
void Serial_Init(void);//初始化
void Serial_SendByte(uint8_t Byte);//打印单个字符
void Serial_SendArray(uint8_t *Array, uint16_t Length);//打印数组
void Serial_SendString(char *String);//打印字符串(但只能选定一个USRATx)
void Serial_SendNumber(uint32_t Number, uint8_t Length);//发送数字
void Serial_Printf(char *format, ...);//打印字符串(可以发送多个USRATx)
#endif
(d)代码说明
1、 Serial_Printf("王哈哈\r\n");
//“\r\n”为换行符
打印中文还需要以下操作,二选其一(选第一比较容易操作):
然后关闭main.c,再打开,编译下载。
记得选择GBK即可打印中文
第二个操作(比较麻烦):
选UTF-8,同上,不过多了下面的步骤:
(3)实物效果
A的ASCII码为41,复位一次STM32发送一个A。
4、串口发送&接收程序
5、USART串口数据包
程序现象,如下: