基于STM32的LoRa无线通信(AS32—TTL-1W)

这篇具有很好参考价值的文章主要介绍了基于STM32的LoRa无线通信(AS32—TTL-1W)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

无线串口简介

项目简介

发送端代码

接收端代码

项目总结


前些天接触到一个小项目,需要使用无线传输的功能,不仅如此还需要远距离的通信,搜索资料后最终选择了泽耀科技的LoRa(AS32—TTL-1W)无线串口模块。之前使用的是100mW的无线模块,经拉距实测在非空旷地带通信距离不到800米。因此这次我选择了1W的无线串口,一般情况下功率越高通信距离就越远。这次还未尽量拉距测试,测试完成后我会继续写一篇测评文章。今天就给大家分享一些我开发的过程以及遇到的一些bug。

无线串口简介

基于STM32的LoRa无线通信(AS32—TTL-1W)

我使用的泽耀科技生产的AS32—TTL-1W,单价55(不含天线),天线单买10元。价格还算公道,毕竟是LoRa模块,图便宜只能买到很多虚标的产品。

1.引脚介绍

该模块一个7个引脚,引脚功能图如下

基于STM32的LoRa无线通信(AS32—TTL-1W)

 MD0,MD1引脚的作用就是修改模块工作状态的(如下图),如果刚开始学搞不懂这些工作状态是什么意思的情况下,收发数据的时候,把MD0,MD1接地即可使用。完成了基本的收发试验后,可以探索一下其它的功能。

基于STM32的LoRa无线通信(AS32—TTL-1W)

 LoRa模块的RX,TX分别接到单片机TX,RX上,如下图。

基于STM32的LoRa无线通信(AS32—TTL-1W)

AUX引脚是用于指示模块工作状态,用户唤醒外部 MCU,配合外部中断即可开发相应的功能。但还是那句话,初学者可以不用考虑这个引脚,给它悬空即可,不影响使用的。

剩下的就是VCC和GND了,商家的参考手册明确给出电源电压小于 4.5V,输出功率会有下降,但对接收功率影响较小。所以我给它接了5V。

2.上位机简介

使用泽耀科技开发的上位机可直接修改模块的波特率,地址,信道,传输方式等参数。最好可以配上泽耀科技生产的usb转ttl一起使用。把模块直接插入上面的单排座即可使用。(配置的时候记得拔掉两个黄色的跳帽)

基于STM32的LoRa无线通信(AS32—TTL-1W)基于STM32的LoRa无线通信(AS32—TTL-1W)

 上位机如图所示

基于STM32的LoRa无线通信(AS32—TTL-1W)

 其实如果只是在两个MCU实现简单的单点通信,直接用厂家的出厂设置的参数就足够了。

项目简介

 项目其实很简单,按下发射端精英板上的KEY_UP按键,接收端精英板的LED0闪一下。按下发射端精英板上的KEY1按键,接收端精英板的LED1闪一下。(代码是移植泽耀科技提供的demo改写的)

基于STM32的LoRa无线通信(AS32—TTL-1W)基于STM32的LoRa无线通信(AS32—TTL-1W)

 发送端代码

main.c

#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "drv_uart.h"
#include "drv_led.h"
#include "drv_AS62.h" 

#define __AS62_TX_MODE__	 //模式选择,屏蔽即为接收模式						


#ifdef __AS62_TX_MODE__
	char *Signal_Go = "a";   //定义字符a
	char *Signal_Stop = "s"; //定义字符s
#else
	uint8_t go[32 ] ={ 'a'};
	uint8_t stop[ 32] ={ 's'};
	uint8_t Go_rx_buffer[ 100 ] = { 0 };
	uint8_t Stop_rx_buffer[100] = { 0 };
	uint8_t g_RxLength = 0;
#endif
 int main(void)
 { 
	int key=0;	
	Init_USART();	        //串口初始化
	ASxx_param_init( );     //模块参数初始化(定点模式,地址0x1234,信道0x17)
	drv_led_init();         //LED初始化
	delay_init();	    	//延时初始化
	KEY_Init();         	//按键初始化
    led_green_off();        
    led_red_off();          //初始化LED灭
	while(1)
	{
 		key=KEY_Scan(0);	//获取键值
		
		if(key==WKUP_PRES)
		{
			led_red_flashing();//LED每发送一次数据闪一下
			GO_On();          //发送字符a·····这里我使用了宏定义发送字符
			delay_ms(500);
			Send_Off;         //模块复位
			led_red_off();
			
		}
		if(key== KEY1_PRES)
		{
			led_green_flashing();//LED每发送一次数据闪一下
			Stop_On;             //发送字符b
			delay_ms(500); 
			Send_Off;            //模块复位
			led_green_off();
		}

	}	 
}

 LoRa.c(此段代码来自泽耀科技的demo)

#include "drv_AS62.h"


//模块配置参数数组
//改变模块参数,只需改变参数数组值,然后初始化即可
const uint8_t g_ASxx_Param_Config[ 6 ] = { 0xC0, 0x12, 0x34, 0x1A, 0x17, 0xC4 };			//定点模式
const uint8_t  g_ASxx_Config_Status_OK[ ] = { 0x4F, 0x4B, 0x0D, 0x0A };


/**
  * @brief :ASxx模块初始化
  * @param :无
  * @note  :按照默认参数初始化,修改默认参数表即可改变模块初始化参数
  * @retval:
  *        @ASxx_Write_OK 写入成功
  *        @ASxx_Write_ERROR 写入失败
  */
ASxxWriteStatusType ASxx_param_init( void )
{
	uint8_t i = 0;
	uint8_t Read_Buff[ 5 ] = { 0 };
	
	drv_uart_tx_bytes((uint8_t *)g_ASxx_Param_Config, 6 );
	drv_uart_rx_bytes( Read_Buff );
	
	for( i = 0; i < 4; i++ )
	{
		if( Read_Buff[ i ] != g_ASxx_Config_Status_OK[ i ] )
		{
			break;
		}
	}
	
	if( 4 == i )
	{
		return ASxx_Write_OK;		//配置成功
	}
	else
	{
		return ASxx_Write_ERROR;	//配置失败
	}
	
}

/**
  * @brief :ASxx模块读配置参数
  * @param :
  * @pReadBuffer:参数返回地址
  * @note  :无
  * @retval:无
  */
void ASxx_read_param( uint8_t *pReadBuffer )
{
	uint8_t Read_Cmd[ 3 ] = { 0xC1, 0xC1, 0xC1 };

	drv_uart_tx_bytes( Read_Cmd, 3 );
	drv_uart_rx_bytes( pReadBuffer );
	
}

/**
  * @brief :ASxx模块读取硬件版本号
  * @param :
  * @pReadBuffer:硬件版本号返回地址
  * @note  :无
  * @retval:无
  */
void ASxx_read_version( uint8_t *pReadBuffer )
{
	uint8_t Read_Cmd[ 3 ] = { 0xC3, 0xC3, 0xC3 };

	drv_uart_tx_bytes( Read_Cmd, 3 );
	drv_uart_rx_bytes( pReadBuffer );
}

/**
  * @brief :ASxx模块读取实际电压值
  * @param :
  * @pReadBuffer:电压值返回地址
  * @note  :无
  * @retval:无
  */
void ASxx_read_voltage( uint8_t *pReadBuffer )
{
	uint8_t Read_Cmd[ 3 ] = { 0xC5, 0xC5, 0xC5 };

	drv_uart_tx_bytes( Read_Cmd, 3 );
	drv_uart_rx_bytes( pReadBuffer );
}

/**
  * @brief :ASxx模块复位
  * @param :无
  * @note  :无
  * @retval:无
  */
void ASxx_reset( void )
{
	uint8_t Read_Cmd[ 3 ] = { 0xC4, 0xC4, 0xC4 };

	drv_uart_tx_bytes( Read_Cmd, 3 );
}

/**
  * @brief :ASxx模块发送数据(定点模式)
  * @param :
  *        @Addr_H:地址高位
  *        @Addr_L:地址低位
  *        @Channel:信道
  *        @pTxBuff:发送数据地址
  *        @Length:发送数据个数
  * @note  :定点模式 数据个数最29个
  * @retval:无
  */
void ASxx_tx_packet( uint8_t Addr_H, uint8_t Addr_L, uint8_t Channel, uint8_t *pTxBuff, uint8_t Length )
{
	uint8_t Header[ 3 ] = { 0 };
	
	Header[ 0 ] = Addr_H;
	Header[ 1 ] = Addr_L;
	Header[ 2 ] = Channel;
	
	drv_uart_tx_bytes( Header, 3 );
	//发送数据
	drv_uart_tx_bytes( pTxBuff, Length );
}

/**
  * @brief :ASxx模块接收数据(定点模式)
  * @param :无
  * @note  :定点模式 数据个数最29个
  * @retval:无
  */
uint8_t ASxx_rx_packet( uint8_t *pRxBuff )
{
	uint8_t Length = 0;
	
	Length = drv_uart_rx_bytes( pRxBuff );
	
	return Length;
}


usart.c

#include "drv_uart.h"


void Init_USART(void)
{
	 GPIO_InitTypeDef GPIO_Structure;
	 USART_InitTypeDef USART_Structure;
	 NVIC_InitTypeDef NVIC_Structure;
	 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

	 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
	
	 //PA9 TX
	 GPIO_Structure.GPIO_Mode=GPIO_Mode_AF_PP;
	 GPIO_Structure.GPIO_Pin=GPIO_Pin_9;
	 GPIO_Structure.GPIO_Speed=GPIO_Speed_50MHz;
	
	 GPIO_Init(GPIOA,&GPIO_Structure);
	 //PA10 RX
	 GPIO_Structure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
	 GPIO_Structure.GPIO_Pin=GPIO_Pin_10;

	 GPIO_Init(GPIOA,&GPIO_Structure);

	 USART_Structure.USART_BaudRate=115200;
	 USART_Structure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
	 USART_Structure.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;
	 USART_Structure.USART_Parity=USART_Parity_No;  
	 USART_Structure.USART_StopBits=USART_StopBits_1;
	 USART_Structure.USART_WordLength=USART_WordLength_8b;
	 USART_ITConfig(USART1, USART_IT_RXNE,  ENABLE);

	 USART_Init(USART1, &USART_Structure);
   USART_Cmd(USART1, ENABLE);

   NVIC_Structure.NVIC_IRQChannel=USART1_IRQn;
	 NVIC_Structure.NVIC_IRQChannelCmd=ENABLE;
	 NVIC_Structure.NVIC_IRQChannelPreemptionPriority=1;
	 NVIC_Structure.NVIC_IRQChannelSubPriority=1;
   NVIC_Init(&NVIC_Structure);

}

/**
  * @brief :串口发送数据
  * @param :
  *			@TxBuffer:发送数据首地址
  *			@Length:数据长度
  * @note  :无
  * @retval:无
  */
void drv_uart_tx_bytes( uint8_t* TxBuffer, uint8_t Length )
{
	while( Length-- )
	{
		while( RESET == USART_GetFlagStatus( UART_PORT, USART_FLAG_TXE ));
		UART_PORT->DR = *TxBuffer;
		TxBuffer++;
	}
}

/**
  * @brief :串口接收数据
  * @param :
  *			@RxBuffer:发送数据首地址
  * @note  :无
  * @retval:接收到的字节个数
  */
uint8_t drv_uart_rx_bytes( uint8_t* RxBuffer )
{
	uint8_t l_RxLength = 0;
	uint16_t l_UartRxTimOut = 0x7FFF;
	
	while( l_UartRxTimOut-- )			//等待查询串口数据
	{
		if( RESET != USART_GetFlagStatus( UART_PORT, USART_FLAG_RXNE ))
		{
			*RxBuffer = (uint8_t)UART_PORT->DR;
			RxBuffer++;
			l_RxLength++;
			l_UartRxTimOut = 0x7FFF;	//接收到一个字符,回复等待时间
		}
		if( 100 == l_RxLength )
		{
			break;		//不能超过100个字节
		}
	}
	
	return l_RxLength;					//等待超时,数据接收完成
}

//发送字符(想通过串口助手查看自己发送的数据可以调用这个函数)
void USART_SendByte_Init(USART_TypeDef* USARTx, uint16_t Data)
{
	
	USART_SendData(USARTx,Data);
  while(USART_GetFlagStatus(USARTx,USART_FLAG_TXE)==RESET);
	
}
//发送字符串(想通过串口助手查看自己发送的数据可以调用这个函数)
void USART_SendStr_Init(USART_TypeDef* USARTx,char *str)
{
	uint16_t i=0;
	do
	{
		USART_SendByte_Init(USARTx,*(str+i));
		i++;
	}while(*(str+i)!='\0');
	
	 while(USART_GetFlagStatus(USARTx,USART_FLAG_TC)==RESET);

}





接收端代码

main.c

#include "led.h"
#include "delay.h"
#include "sys.h"
#include "drv_uart.h"
#include "drv_led.h"
#include "drv_AS62.h" 

//#define __AS62_TX_MODE__		//接收模式开启							

void delay(uint16_t time)       //延时函数
{   
	uint16_t i=0;               
	while(time--)
	{
		i=12000;
		while(i--);
	}
	
}

#ifdef __AS62_TX_MODE__
	char *Signal_Go = "a";
	char *Signal_Stop = "s";
	
#else
	uint8_t go[ 8 ] ={ 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a' };
	uint8_t stop[ 8 ] ={ 's', 's', 's', 's', 's', 's', 's', 's' };
  uint8_t Go_rx_buffer[ 100 ] = { 0 };
	uint8_t Stop_rx_buffer[100] = { 0};
	uint8_t g_RxGO = 0;
  uint8_t g_RxSTOP = 0;
#endif

int main( void )
{	
    drv_uart_init();
	ASxx_param_init( );
	drv_led_init( );
  led_green_off();
  led_red_off( );
	while(1)
	{

	}

 }
 void USART1_IRQHandler (void)    //串口中断服务函数
 {
	 char temp=0;
	 if(USART_GetITStatus( USART1, USART_IT_RXNE)!=RESET)
    {
			temp =  USART_ReceiveData(USART1);
			if(temp=='a')
			{
	      led_green_flashing();        //接收到字符‘a’led闪一次

				delay(500);
				led_green_off();
			}		
			if(temp=='s')
			{
	      led_red_flashing();           //接收到字符‘b’led闪一次
				delay(500);
				led_red_off()	;
			}		
		}
 }




由于接收端的代码与发射端除了main函数之外,其它函数几乎一致,所以我这里只上传了main函数里的内容,如果想要完整代码可以私信我。

项目中遇到的小bug

在写接收端的串口中断服务函数的时候,在实现灯的闪烁的时候,开始我的延时函数调用的是定时器中断延时。但程序编译运行后发现程序根本无法执行闪烁的效果,接收到指定的字符后led一直保持常亮的状态。我百思不得其解,根据程序执行的逻辑从表面上看没毛病呀!尝试过各种猜想,一开始还傻傻的以为是中断标志位没有清除,但后来发现都不是。然后我抱着瞎猫碰到死耗子的心理,把定时器中断延时改成了传统上的“粗延时”,编译执行后居然成功了,接收到指定字符后可以实现闪烁了。这着实让我既惊讶又惊喜,这个折磨我这么多天的bug居然就这么解决了。但我到现在都不知道是什么原理,之前用Wemos实现串口中断的时候也是在串口中断服务函数中加入delay()后,程序也出现了类似的bug。难道串口中断服务函数就是这么奇葩吗?欢迎大佬前来指点!!!

项目总结

这个项目虽然简单,但我实现的过程中还是挺坎坷的。全网适用于泽耀科技产品的例程并不多,根据泽耀科技提供的demo写了快一个星期(毕竟本人也是单片机小白),网上大多数都是关于安信可的或者NFR2401相关的例程比较多一些。尤其是NFR2401的例程多到快烂大街了,所以想在短时间内开发出项目或是单片机基础薄弱的同学选择NFR2401开发也是一个不错之选。关于LoRa无线串口这个模块我了解的还仅仅是冰山一角,还有很多功能都没有开发出来,本人也才疏学浅,文章中如有错误欢迎大佬在评论区指正,如想要源代码的小伙伴也可以私信我。文章来源地址https://www.toymoban.com/news/detail-408996.html

到了这里,关于基于STM32的LoRa无线通信(AS32—TTL-1W)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 通信工程毕设 stm32与GSM的远程无线智能报警系统(项目开源)

    🔥 这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要求,这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师的要求。 为了大家能够顺利以及最少的精力通过毕设,学长分享优质毕业设计项目,今天

    2024年02月19日
    浏览(38)
  • STM32 F103C8T6学习笔记7:双机无线串口通信

    今日尝试配通俩个C8T6单片机之间的无线串口通信,文章提供原理,源码,测试效果图,测试工程下载: 目录 传输不规范问题: 串口通信资源: 单个串口资源理解: 单片机串口资源: 测试目标与测试硬件连接: 串口初始化与串口中断接收逻辑: 串口初始化: 初步测试能否

    2024年02月09日
    浏览(33)
  • 【物联网无线通信技术】LoRa从理论到实现(SX1268)

    文章先从LoRa的物联网通信技术前辈们讲起,慢慢引出了这种功耗又低,距离又远的无线通信技术,然后又似庖丁解牛一般,从物理层到链路层,详细的介绍了LoRa这种技术的组成,最后以一种实际的原理与嵌入式软件实现,让读者近距离接触到基于LoRa这种无线通信技术产品的

    2024年02月10日
    浏览(29)
  • 基于I.MX6ULL的Linux C多线程物联网网关+STM32+Qt上位机+Linux C++多线程服务器(含web)的多种无线通信系统的智慧农场

    我国是农业大国,而非农业强国。近30年来农业高产量主要依靠农药化肥的大量投入,大部分化肥和水资源没有被有效利用而随地弃置,导致大量养分损失并造成环境污染。我国农业生产仍然以传统生产模式为主,传统耕种只能凭经验施肥灌溉,不仅浪费大量的人力物力,也

    2024年04月14日
    浏览(57)
  • 基于人工噪声的无线通信物理层安全研究

            无线通信的普及性源于它的广播特性,能够让用户不受地理位置随时随地获取信息。但是这种广播特性同时也让窃听者窃取信息变得容易又隐蔽,无线通信的安全性因此很难保证。同时,无线信道的不确定性和时变性也给无线通信带来了新的挑战,但是,如果能合

    2024年04月09日
    浏览(66)
  • ESP8266初次如何实现无线通信(基于电脑与ESP8266)

    本次软件是需要串口调试助手,网络调试助手,KEIL5                             下面图标依次排列 本次硬件是需要一个ESP8266模块,一个stm32f103c8t6芯片,一个USB转TTL模块 ESP8266是一个微小的且集成的国产WIFI模块,它有很多种型号,但是使用

    2023年04月20日
    浏览(24)
  • 基于LoRa技术的STM32处理器无线程序升级系统设计(学习)

    基于LoRa技术的STM32处理器无线程序升级系统设计 设计并实现了一款基于LoRa技术对STM32F767系列处理器通过无线方式升级程序的系统。该系统的硬件结构包括:无线发送端、无线接收端及待升级程序的STM32F767处理器3个部分。 发送端将程序的数据文件通过LoRa技术传递给接收端,

    2024年02月12日
    浏览(25)
  • 基于STM32的正点原子LORA模块通信网络

    LoRa是semtech公司开发的一种低功耗局域网无线标准,其名称“LoRa”是远距离无线电(Long Range Radio),它最大特点就是在同样的功耗条件下比其他无线方式传播的距离更远,实现了低功耗和远距离的统一,它在同样的功耗下比传统的无线射频通信距离扩大3-5倍。 距离往往可达

    2023年04月08日
    浏览(31)
  • 毕业设计 基于51单片机环境监测设计 光照 PM2.5粉尘 温湿度 2.4G无线通信

    选题之前,同学们要弄明白一件事情,做毕业设计是干什么用的! 这里我告诉大家,毕业设计对于你来说,不是让你去搞研究,掌握运用所学知识的,也不是让你去比谁做的毕业设计多么牛逼,多么厉害。 说白点,它的作用就是一个,让你顺利毕业,能够拿到学位证,毕业

    2023年04月08日
    浏览(42)
  • 基于瑞丽多径信道的无线通信信道均衡算法matlab仿真,对比MMSE,ZF-DFE,MMSE-DFE

    目录 1.算法仿真效果 2.算法涉及理论知识概要 3.MATLAB核心程序 4.完整算法代码文件 matlab2022a仿真结果如下:         信道均衡(Channel equalization)是指为了提高衰落信道中的通信系统的传输性能而采取的一种抗衰落措施。它主要是为了消除或者是减弱宽带通信时的多径时延带

    2024年02月05日
    浏览(31)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包