文章目录
前言
一个学习单片机的小白~ 有错误评论区或私信指出~
一、串口结构体及库函数
串口USART结构体:
typedef struct
{
uint32_t USART_BaudRate;
uint16_t USART_WordLength;
uint16_t USART_StopBits;
uint16_t USART_Parity;
uint16_t USART_Mode;
uint16_t USART_HardwareFlowControl;
} USART_InitTypeDef;
串口USART相关库函数:
void USART_DeInit(USART_TypeDef* USARTx);
void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef*
USART_InitStruct);
void USART_StructInit(USART_InitTypeDef* USART_InitStruct);
void USART_ClockInit(USART_TypeDef* USARTx, USART_ClockInitTypeDef*
USART_ClockInitStruct);
void USART_ClockStructInit(USART_ClockInitTypeDef*
USART_ClockInitStruct);
void USART_Cmd(USART_TypeDef* USARTx, FunctionalState NewState);
void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT,
FunctionalState NewState);
void USART_DMACmd(USART_TypeDef* USARTx, uint16_t USART_DMAReq,
FunctionalState NewState);
void USART_SetAddress(USART_TypeDef* USARTx, uint8_t USART_Address);
void USART_WakeUpConfig(USART_TypeDef* USARTx, uint16_t USART_WakeUp);
void USART_ReceiverWakeUpCmd(USART_TypeDef* USARTx, FunctionalState
NewState);
void USART_LINBreakDetectLengthConfig(USART_TypeDef* USARTx, uint16_t
USART_LINBreakDetectLength);
void USART_LINCmd(USART_TypeDef* USARTx, FunctionalState NewState);
void USART_SendData(USART_TypeDef* USARTx, uint16_t Data);
uint16_t USART_ReceiveData(USART_TypeDef* USARTx);
void USART_SendBreak(USART_TypeDef* USARTx);
void USART_SetGuardTime(USART_TypeDef* USARTx, uint8_t
USART_GuardTime);
void USART_SetPrescaler(USART_TypeDef* USARTx, uint8_t
USART_Prescaler);
void USART_SmartCardCmd(USART_TypeDef* USARTx, FunctionalState
NewState);
void USART_SmartCardNACKCmd(USART_TypeDef* USARTx, FunctionalState
NewState);
void USART_HalfDuplexCmd(USART_TypeDef* USARTx, FunctionalState
NewState);
void USART_OverSampling8Cmd(USART_TypeDef* USARTx, FunctionalState
NewState);
void USART_OneBitMethodCmd(USART_TypeDef* USARTx, FunctionalState
NewState);
void USART_IrDAConfig(USART_TypeDef* USARTx, uint16_t USART_IrDAMode);
void USART_IrDACmd(USART_TypeDef* USARTx, FunctionalState NewState);
FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t
USART_FLAG);
void USART_ClearFlag(USART_TypeDef* USARTx, uint16_t USART_FLAG);
ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT);
void USART_ClearITPendingBit(USART_TypeDef* USARTx, uint16_t
USART_IT);
二、实现串口发送(库函数)
1.程序设计
软件流程设计
- 初始化系统
- 初始化GPIO、串口外设时钟
- 初始化串口引脚
- 串口发送
2.代码
//初始化系统
void Usart_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
//TX
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);
//RX
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_Init(USART1,&USART_InitStructure);
USART_Cmd(USART1,ENABLE);
}
#include "stm32f10x.h"
#include "main.h"
#include "usart.h"
int main()
{
Usart_Init();
while(1)
{
USART_SendData(USART1,'O');
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET );
USART_SendData(USART1,'K');
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET );
}
}
三.串口接收
1.串口接收(普通)
软件流程设计
- 初始化系统
- 初始化GPIO、串口外设、LED时钟
- 初始化串口和LED引脚
- 串口发送控制LED灯
//串口初始化
#include "usart.h"
#include "stm32f10x.h" // Device header
#include <stdio.h>
void Usart_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
//TX
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);
//RX
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_Init(USART1,&USART_InitStructure);
USART_Cmd(USART1,ENABLE);
}
#include "stm32f10x.h"
#include "main.h"
#include "usart.h"
#include "LED.h"
#include <stdio.h>
int main()
{
LED_Init();
Usart_Init();
char temp;
while(1)
{
if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE) != RESET)//判断是否接受到数据
{
temp = USART_ReceiveData(USART1);//读收到的数据
if(temp == 'A')
{
USART_SendData(USART1,temp);
GPIO_ResetBits(GPIOA,GPIO_Pin_1);
}
if(temp == 'B')
{
USART_SendData(USART1,temp);
GPIO_SetBits(GPIOA,GPIO_Pin_1);
}
}
USART_ClearFlag(USART1,USART_FLAG_RXNE);//清除标志位
}
}
2.串口中断接收
软件流程设计
- 初始化系统
- 初始化GPIO、串口外设、串口中断、NVIC、LED时钟
- 初始化串口和LED引脚
- 写串口中断控制语句
- 串口发送控制LED灯
#include "usart.h"
#include "stm32f10x.h" // Device header
#include <stdio.h>
void Usart_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
//TX
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);
//RX
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_Init(USART1,&USART_InitStructure);
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//配置串口中断
USART_Cmd(USART1,ENABLE);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
#include "stm32f10x.h"
#include "main.h"
#include "usart.h"
#include "LED.h"
#include <stdio.h>
int main()
{
LED_Init();
Usart_Init();
while(1)
{
}
}
//串口中断函数
void USART1_IRQHandler(void)
{
char temp;
if(USART_GetITStatus(USART1,USART_IT_RXNE) != RESET )//判断串口中断接收是否产生
{
temp = USART_ReceiveData(USART1);//读数据
if(temp == 'A')
{
putchar(temp);
GPIO_ResetBits(GPIOA,GPIO_Pin_1);
}
if(temp == 'B')
{
putchar(temp);
GPIO_SetBits(GPIOA,GPIO_Pin_1);
}
}
USART_ClearITPendingBit(USART1,USART_IT_RXNE);
}
3. 串口发送字符串函数
思路:C语言字符串类似于字符数组最后一位是’\0’,可以用循环遍历,每遍历一遍发送一个数据,遍历到’\0’时结束循环,本质上还是传输一个字符数据不过是一次发一连串字符。
代码实现:
void USART_SendString(USART_TypeDef* USARTx, char * String)
{
uint16_t i = 0;
do
{
USART_SendData(USARTx,*(String + i));
while( USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET );
i++;
}while(*(String + i) != '\0');
while( USART_GetFlagStatus(USART1,USART_FLAG_TC) == RESET );
}
4.串口实现printf(重定向)
修改printf底层代码,重载函数fputc
代码实现:
int fputc(int ch,FILE *f)
{
USART_SendData(USART1,(uint8_t)ch);
while( USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET );
return (ch);
}
5. 串口实现scanf(重定向)
修改scanf底层代码,重载函数fgetc
代码实现:
int fgetc(FILE *f)
{
while( USART_GetFlagStatus(USART1,USART_FLAG_RXNE) == RESET );
return (int)USART_ReceiveData(USART1);
}
注:使用priintf、scanf记得勾选UseMicroLIB