串口发送/接收函数
HAL_UART_Transmit(); //串口发送数据,轮询发送
HAL_UART_Receive(); //串口接收数据,轮询发送
HAL_UART_Transmit_IT(); //串口中断模式发送
HAL_UART_Receive_IT(); //串中断模式接收
函数原型参数解析:
以阻塞的方式发送指定字节的数据
HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size, uint32_t Timeout)
参数 | 解析 |
---|---|
UART_HandleTypeDef huart | UART_HandleTypeDef 结构体类型指针变量 |
uint8_t * pData | 指向要发送的数据地址 |
uint16_t Size | 要发送的数据大小,以字节为单位 |
uint32_t Timeout | 设置的超时时间,以ms单位 |
以中断的方式接收指定字节的数据
HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart,
uint8_t *pData, uint16_t Size)
此函数执行完后将清除中断,需要再次调用以重新开启中断
参数 | 解析 |
---|---|
UART_HandleTypeDef huart | UART_HandleTypeDef 结构体类型指针变量 |
uint8_t * pData | 指向接收数据缓冲区 |
uint16_t Size | 要发送的数据大小,以字节为单位 |
串口中断回调函数
HAL_UART_IRQHandler(UART_HandleTypeDef*huart); //串中断处理函数
HAL_UART_TxCpltCallback(UART_HandleTypeDef*huart); //发送中断回调函数
HAL_UART_RxCpltCallback(UART_HandleTypeDef*huart); //接收中断回调函数
HAL_UART_Transmit(&huart1,(unsigned char *)"hello world\r\n", strlen("hello world\r\n"),100);
int fputc(int ch, FILE *f)
{
unsigned char temp[1]={ch};
HAL_UART_Transmit(&huart1,temp,1,0xffff);
return ch;
}
unsigned char uart1_buf[20] = {0}; //接收数据缓冲区
while(1)
{
HAL_UART_Receive(&huart1, uart1_buf, 19, 100);
HAL_UART_Transmit(&huart1, uart1_buf, strlen(uart1_buf), 100);
if(strstr(uart1_buf,"open") != NULL)
HAL_GPIO_WritePin(LED2_GPIO_Port,LED2_Pin,GPIO_PIN_RESET);
else if( strstr(uart1_buf,"close") != NULL )
HAL_GPIO_WritePin(LED2_GPIO_Port,LED2_Pin,GPIO_PIN_SET);
memset(uart1_buf, 0, strlen(uart1_buf));
}
//usart.c 函数封装
void SendString(UART_HandleTypeDef *huart, char *String)
{
HAL_UART_Transmit_IT(huart,(uint8_t *)String,strlen(String));
}
//main.c 函数调用
SendString(&huart1,"haha\r\n");
//串口中断接收变量定义
unsigned char UART1_RX_Buffer[256]; //串口接收数组
unsigned char UART1_RX_index = 0; //接收下标计数器
unsigned char UART1_RX_flag = 0; //接收下标计数器
//开启接收中断,一次接收1个字符
HAL_UART_Receive_IT(&huart1, (uint8_t *)&RX_ch, 1);
//中断服务函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
unsigned char RX_ch = '\0'; //接收中断缓冲
if(huart->Instance == USART1)
{
if(UART1_RX_index >= 255) //溢出判断
{
UART1_RX_index = 0;
memset(UART1_RX_Buffer,0x00,sizeof(UART1_RX_Buffer));
}
else //正常接收数据,并放入数组
{
UART1_RX_Buffer[UART1_RX_index++] = RX_ch; //接收数据转存
if((UART1_RX_Buffer[UART1_RX_index-1] == 0x0A)&&(UART1_RX_Buffer[UART1_RX_index-2] == 0x0D)) //判断结束位
{
HAL_UART_Transmit(&huart1, (uint8_t *)&UART1_RX_Buffer, UART1_RX_index,0xFFFF); //将收到的信息发送出去
UART1_RX_index = 0;
memset(UART1_RX_Buffer,0x00,sizeof(UART1_RX_Buffer)); //清空数组
}
}
//命令执行语句 对于复杂执行语句立flag, 在main函数中执行
if(strstr((const char *)UART1_RX_Buffer,"open") != NULL)
HAL_GPIO_WritePin(LED2_GPIO_Port,LED2_Pin,GPIO_PIN_RESET);
else if( strstr((const char *)UART1_RX_Buffer,"close") != NULL )
HAL_GPIO_WritePin(LED2_GPIO_Port,LED2_Pin,GPIO_PIN_SET);
HAL_UART_Receive_IT(&huart1, (uint8_t *)&RX_ch, 1); //再开启接收中断
}
}
使能时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能GPIOA时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); //使能USART1时钟
使能GPIO口
GPIO_InitTypeDef GPIO_InitStructure;
//USART1_TX GPIOA.9
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
//USART1_RX GPIOA.10初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PA10
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA
串口参数配置
USART_InitTypeDef USART_InitStructure;
//USART 初始化设置
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
NVIC中断配置
NVIC_InitTypeDef NVIC_InitStructure;
//Usart1 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //开启串口接受中断
串口1初始化程序
void Usart1_Init(u32 bound)
{
//GPIO端口设置
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); //使能USART1,GPIOA时钟
//USART1_TX GPIOA.9
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9
//USART1_RX GPIOA.10初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10
//Usart1 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
//USART 初始化设置
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_ITConfig(USART1, USART_IT_RXNE, ENABLE); //开启串口接受中断
USART_Cmd(USART1, ENABLE); //使能串口1
}
printf重定向
//串口1输出重定向
int fputc(int ch, FILE *f)
{
USART_SendData(USART1,(uint8_t)ch);
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET);
return (ch);
}
//串口1输入重定向
int fgetc(FILE *f)
{
while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE)==RESET);
return (int)USART_ReceiveData(USART1);
}
串口写字节函数
/*
* 功能:串口写字节函数
*
* 参数1:USARTx :串口号
*
* 参数2:Data :需写入的字节
*/
void USART_Send_Byte(USART_TypeDef* USARTx, uint16_t Data)
{
USART_SendData(USARTx, Data);
while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE)==RESET);
}
串口发送字符串函数
/*
* 函数名称: Usart_SendString
*
* 函数功能: 串口数据发送
*
* 入口参数: USARTx:串口组
*
* str:要发送的数据
*
* len:数据长度
*/
void Usart_SendString(USART_TypeDef *USARTx, unsigned char *str, unsigned short len)
{
unsigned short count = 0;
for(; count < len; count++)
{
USART_SendData(USARTx, *str++); //发送数据
while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET); //等待发送完成
}
}
串口格式化打印
/*
* 函数名称: UsartPrintf
*
* 函数功能: 格式化打印
*
* 入口参数: USARTx:串口组
* fmt:不定长参
*/
#include
void UsartPrintf(USART_TypeDef *USARTx, char *fmt,...)
{
unsigned char UsartPrintfBuf[296];
va_list ap;
unsigned char *pStr = UsartPrintfBuf;
va_start(ap, fmt);
vsnprintf((char *)UsartPrintfBuf, sizeof(UsartPrintfBuf), fmt, ap); //格式化
va_end(ap);
while(*pStr != 0)
{
USART_SendData(USARTx, *pStr++);
while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET);
}
}
//串口接收变量定义
unsigned char usart1_buffer[128] = {'\0'}; //接收缓存
unsigned char usart1_index = 0; //中断下标索引
unsigned char usart1_flag = 0; //中断标志位
//串口中断服务函数
void USART1_IRQHandler(void)
{
uint16_t ch; //串口接收字节缓冲
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //串口收到数据
{
if(usart1_index == 127) //下标溢出
{
usart1_index = 0;
memset(usart1_buffer,0x00,sizeof(usart1_buffer));
}
ch = USART_ReceiveData(USART1); //串口接收1个字节
usart1_buffer[usart1_index++] = ch; //数据存入接收数组
if((usart1_buffer[usart1_index-1] == 0x0A)&&(usart1_buffer[usart1_index-2] == 0x0D)) //判断结束位
{
Usart_SendString(USART1,usart1_buffer,usart1_index);
usart1_index = 0;
//执行命令语句 对于复杂执行语句立flag, 在main函数中执行
if(strstr((const char *)usart1_buffer,"open") != NULL) //检测到open信号
LED1 = 0;
if(strstr((const char *)usart1_buffer,"close") != NULL)
LED1 = 1;
memset(usart1_buffer,0x00,sizeof(usart1_buffer)); //清空数组
}
USART_ClearFlag(USART1, USART_FLAG_RXNE); //清除中断标志
}
}
初始化函数:
void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct);
串口使能函数:
void USART_Cmd(USART_TypeDef* USARTx, FunctionalState NewState);
中断配置函数:
void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT, FunctionalState NewState);
串口发送函数:
void USART_SendData(USART_TypeDef* USARTx, uint16_t Data);
串口接收读取函数:
uint16_t USART_ReceiveData(USART_TypeDef* USARTx);
获取响应的串口表示位:
FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG);
中断状态位获取:
ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT);