140 lines
7.2 KiB
C
140 lines
7.2 KiB
C
#include "USART3.h"
|
||
|
||
/**
|
||
* @brief LoRa的初始化函数
|
||
* @note 使用USART3串口(PB10->LoRa_RX,PB11->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 *pucArray,usLength
|
||
* @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 */
|
||
uint32_t ulRxData = USART_ReceiveData(USART3);
|
||
while (ulRxData != 0xFF)
|
||
{
|
||
/* code */
|
||
ucRxBuffer[ucIndex++] = ulRxData;
|
||
}
|
||
USART_ClearITPendingBit(USART3, USART_IT_RXNE);
|
||
}
|
||
}
|