Files
FreeRTOS_LoRa_Environment_A…/STM32/Environment_Node/System/USART3.c

139 lines
7.3 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "USART3.h"
/**
* @brief LoRa的初始化函数
* @note 使用USART3串口PB10->LoRa_RXPB11->LoRa_TX波特率设置为115200。
* @param ulUsart3Baudrate
* @retval None
*/
void vUsart3Init(uint32_t ulUsart3Baudrate)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = USART3_GPIO_PIN_TX;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = USART3_GPIO_PIN_RX;
GPIO_Init(GPIOB, &GPIO_InitStructure);
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = ulUsart3Baudrate; // 设定后USART_Init函数内部会自动算好9600对应的分频系数并写到BRR寄存器
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 硬件流控制,不使用流控
USART_InitStructure.USART_Mode = USART_Mode_Tx|USART_Mode_Rx; // 串口模式,如果既使用输入和输出模式就用或符号,发送模式和接收模式
USART_InitStructure.USART_Parity = USART_Parity_No; // 无校验位
USART_InitStructure.USART_StopBits = USART_StopBits_1; // 一位停止位
USART_InitStructure.USART_WordLength = USART_WordLength_8b; // 字长不需要校验字长就选择8位
USART_Init(USART3,&USART_InitStructure);
// 上面是串口的查询模式如果使用中断还需要开启中断配置NVIC
USART_ITConfig(USART3,USART_IT_RXNE,ENABLE); // 选择RXNE的中断,并开启RXNE标志位到NVIC的输出如果RXNE标志位置1就会向NVIC申请中断之后可以在中断函数中接收数据
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4); // 分组分组4为4bit抢占优先级和0bit响应优先级抢占优先级可设置为0-15。由于FreeRTOS没有响应优先级而优先级分组4相当于4位抢占优先级和0位响应优先级。
NVIC_InitTypeDef NVIC_InitStructure; // 初始化NVIC的USART1通道
NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn; // 中断通道
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 5; // 抢占优先级配置根据FreeRTOS设置配置在范围内可以调用FreeRTOS的以“FromISR()”结尾的api函数。
// NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; // 响应优先级配置,用不上了
NVIC_Init(&NVIC_InitStructure); // 指向NVIC_InitStructure的地址
USART_Cmd(USART3,ENABLE);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = USART3_GPIO_PIN_ATK_MD0;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = USART3_GPIO_PIN_ATK_AUX;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
/**
* @brief 串口发送单个字节函数
* @note 调用这个函数就可以从TX引脚发送一个字节数据。
* @param ucByte
* @retval None
*/
void vUsart3SendByte(uint8_t ucByte)
{
USART_SendData(USART3, ucByte); // 调用这个函数Byte就写入TDR寄存器了
// 写完之后还需要等待一下等TDR的数据转移到移位寄存器就可以了如果数据还在TDR寄存器中再写入数据就会产生数据覆盖所以在发送之后还需要等待一下标志位
while(USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET); // 发送数据寄存器空标志位等待TXE置1所以需要套一个while循环 TXE:发送数据寄存器空发送完标志位自动置0不用手动复位。
}
/**
* @brief 串口发送数组函数
* @note 一般用于16进制模式下。
* @note uint8_t的指针类型指向待发送数组的首地址,由于数组无法判断是否结束所以需要再传递一个Length进来。
* @param *pucArrayusLength
* @retval None
*/
void vUsart3SendArray(uint8_t *pucArray, uint16_t usLength)
{
for(uint16_t i = 0; i < usLength; i ++) // for循环执行Length次可以对Array数据进行遍历实际定义数组不要超出uint16_t的范围即可
{
vUsart3SendByte(pucArray[i]); // 依次取出数组Array的每一项
}
}
/**
* @brief 串口发送字符串函数
* @note 将字符串封装成指针数组的形式,定义数组长度直到检测到字符串的末尾结束,并将字符串根据长度拆成带个字符发送。
* @param *pcString
* @retval None
*/
void vUsart3SendString(char *pcString) // 给uint8_t *也可以,由于字符串自带一个标志位,所以就不需要再传递长度参数了
{
for(uint8_t i = 0; pcString[i] != '\0'; i++) // 循环结束就可以用标志位来判断了,填'\0'是空字符的转义字符表示形式和直接写0是一样的
{
vUsart3SendByte(pcString[i]); // 将String字符串一个个取出来通过SendByte发送
}
}
/**
* @brief printf重定向函数
* @note fputc是printf函数的底层printf函数在打印的时候就是不断调用fputc函数打印。
* @param ch,*f
* @retval ch
*/
int fputc(int ch, FILE *f)
{
vUsart3SendByte(ch);
return ch;
}
/**
* @brief printf封装函数
* @note 第一个参数是接收字符串,第二个是接收可变参数列表。
* @param *format,...
* @retval None
*/
void vUsart3Printf(char *format, ...)
{
char String[100];
va_list arg; // arg是定义一个参数列表变量
va_start(arg, format); // 从format位置开始接收参数表放在arg里面
vsprintf(String, format, arg); // 封装格式要用vsprintf因为sprintf只能接收直接写的参数打印字符串格式是format参数表是arg
va_end(arg); // 释放参数表
vUsart3SendString(String);
}
void USART3_IRQHandler(void)
{
if (USART_GetITStatus(USART3, USART_IT_RXNE) == SET)
{
/* code */
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
uint8_t ulRxData = (uint8_t)USART_ReceiveData(USART3);
xQueueSendFromISR(xQueueUsart3IrqHdlr, &ulRxData, &xHigherPriorityTaskWoken);
USART_ClearITPendingBit(USART3, USART_IT_RXNE);
/* 问题根源:请求上下文切换 */
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
}