STM32 DX-LR01数据收发实现详解:解决串口通信难题
硬件选择
MCU选用目前较受初学者欢迎的STM32F103C8T6。此MCU内部外设丰富,具有三个串口、四个定时器、两个IIC、两个SPI等等,选其作为小形项目或节点的主控制器是非常合适的。
通信模块选用大厦龙雀的LR01,其推出的初学者套餐也是非常友好。LR01具有体积小、通信距离远(可在城市中3.8km内通信)、抗干扰性强、应用场景广泛等特点,使用AT指令配置必要参数便可实现数据互传,非常适用于小型的通信项目。
点击查看详情(初次购买有优惠)
LR01有七个引脚,具体如下:
但本文只需串口即可实现,更多使用配置请参考手册。
模块连接VCC—3.3-5V,GND—GND,RX—PA2(TX),TX—PA3(RX)。
AT配置
配置为MODE0透明传输,传输速率以及信道要一样。
相关程序
串口配置
void USART2_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
// 打开串口GPIO的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO, ENABLE);
// 打开串口外设的时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
// 将USART Tx的GPIO配置为推挽复用模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 将USART Rx的GPIO配置为浮空输入模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* 嵌套向量中断控制器组选择 */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
/* 配置USART为中断源 */
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
/* 抢断优先级*/
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;
/* 子优先级 */
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
/* 使能中断 */
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
/* 初始化配置NVIC */
NVIC_Init(&NVIC_InitStructure);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);// 串口中断优先级配置
// 配置串口的工作参数
// 配置波特率
USART_InitStructure.USART_BaudRate = 115200;
// 配置 针数据字长
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
// 配置停止位
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(USART2, &USART_InitStructure);
// 使能串口
USART_Cmd(USART2, ENABLE);
USART_ClearFlag(USART2, USART_FLAG_TC);//清除发送缓存区以防发送卡死
// 使能串口接收中断
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
USART_ITConfig(USART2, USART_IT_IDLE, ENABLE);//开启IDLE中断,防止串口只接收第一个字节就停
}
发送函数
void Usart_SendString(USART_TypeDef *USARTx, char *str, unsigned short len)
{
unsigned short count = 0;
for(; count < len; count++)
{
USART_SendData(USARTx, *str++); //发送数据
while(RESET == USART_GetFlagStatus(USARTx, USART_FLAG_TC)); //等待发送完成
}
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//发送完毕后打开串口接收中断
}
相关问题:为什么程序卡死在 while(RESET == USART_GetFlagStatus(USARTx, USART_FLAG_TC));?
肯定要检查配置,USART2是总线2,而引脚和复用功能的时钟是总线1,配置时别混了;引脚的配置也别忽略,PA3输入没有速度;还有查看串口是否使能,也就是这句USART_Cmd(USART2, ENABLE)。
串口中断
char RxData[10] = "";
int Receive_sum = 0;
void USART2_IRQHandler(void)
{
if (USART_GetITStatus(USART2, USART_IT_RXNE) == SET)
{
USART_ClearITPendingBit(USART2, USART_IT_RXNE);
RxData[Receive_sum++] = USART_ReceiveData(USART2);
}
if(USART_GetITStatus(USART2,USART_IT_IDLE) != RESET)//接收到一帧数据
{
USART2->SR;//先读SR
USART2->DR;//再读DR
Receive_sum = 0;//数组下标一定记得清零,不然会只有一次接收数据
printf("%s", RxData);//打印看结果
}
}
相关问题:为什么串口只能接收一次数据?或只能接收第一个字节?
只能接收一次数据是因为接收数组的下标未清零,导致数组容量溢出则无法获取数据。还可能是中断优先级低于USART1(打印使用)。
只能接收第一个字节是因为在中断函数中执行了逻辑运算代码,所以不要加入任何数据解析之外的逻辑(如延时函数、浮点数运算等等)。
因为发送和接收同时使用,串口的收发都是字符型的,所以在发送前进行格式转换并将接收中断关闭以防乱码。如:
int i,len = 2;
USART_ITConfig(DEBUG_USART2, USART_IT_RXNE, DISABLE);//关闭串口接收中断
while(len --){
sprintf(DATA_BUF,"XS001case total:%d out:%d",Total_p,out_p);//将数据转化为字符串
Usart_SendString(USART2, DATA_BUF, strlen(DATA_BUF));
printf(DATA_BUF);
printf("\r\n");
strcpy(DATA_BUF, "");//发送完毕后将数组清零
delay_ms(500);
}
相关问题:发送无数据?或没收到?
实验后发现只进行一次数据发送,另一个LR01模块是收不到的,所以这里有个while,循环了两次也就是发送了两次。
LR01与LORA模块一样,具有三种通信模式:透明传输、定点传输、广播传输。定点传输与广播传输都需要以HEX形式发送,串口上勾选即可进行精准通信,但鄙人使用单片机转换了多种形式发送但接收端依旧收不到数据,所以使用了透明传输。(希望哪位大佬测试成功了教教我TAT
要实现定点传输或准确接收就要做一些逻辑处理,如在发送的数据前加上标识符,并在接收端判断数据头,如符合了便进行下一步逻辑程序。
void receive_data(){
int num1 = 0;
if(RxData[0] == 'X' && RxData[1] == 'S'){
printf(RxData);
sscanf(&RxData[3],"%d",&num1);
Total_p = num1;
strcpy(RxData, "");
}
}
实现结果
如何文章对你有帮助,可以打赏吃颗糖吗~
技术交流:XXS05077(备注来意)
作者:小蛋没有芯片