新大陆STM32开发Lora通用库函剖析

物联网竞赛STM32开发Lora通用库函剖析

一、LED函数解析

在开发板当中有两个LED灯引脚分别是PA3和PB8(低电平有效)
重点函数:
GpioWrite(&Led1,0);		//点亮LED1
GpioWrite(&Led1,1);		//熄灭LED1
GpioWrite(&Led2,0);		//点亮LED1
GpioWrite(&Led2,1);		//点亮LED1
GpioToggle(&Led1);		//LED1状态翻转
GpioToggle(&Led2);		//LED1状态翻转

关于GPioWrite();
实现功能:控制指定的LED灯的高低电平是实现亮灭效果
底层函数:
void GpioMcuWrite( Gpio_t *obj, uint32_t value )
{
    if( ( obj == NULL ) || ( obj->port == NULL ) )
    {
        assert_param( FAIL );
    }
    // Check if pin is not connected
    if( obj->pin == NC )
    {
        return;
    }
    HAL_GPIO_WritePin( obj->port, obj->pinIndex , ( GPIO_PinState )value );
}
解析:GpioWrite函数只需要输入两个参数分别是定义LED灯的位置以及01来控制亮灭,LED1对应的引脚是PA3
LED2对应的引脚是PB8通过底层代码得知其实本质上还是调用了HAL库当中的 HAL_GPIO_WritePin()来控制LED的高低电平。
    
关于GpioToggle();
实现功能:指定对应LED灯进行电平翻转如果当前电平为0执行函数后会变为1
底层函数:
void GpioMcuToggle( Gpio_t *obj )
{
    if( ( obj == NULL ) || ( obj->port == NULL ) )
    {
        assert_param( FAIL );
    }

    // Check if pin is not connected
    if( obj->pin == NC )
    {
        return;
    }
    HAL_GPIO_TogglePin( obj->port, obj->pinIndex );
}

解析:GpioToggle参数只需要传入指定的LED灯即可,调用的也是hal库的HAL_GPIO_TogglePin()函数
    

LED灯效果函数文件
在Lora开发库当中也有实现许多LED灯效果的函数如呼吸灯和LED轮流闪烁
在使用对应函数时需要导入led_light.h
导入代码:#include “led_light.h”
    
实现呼吸灯函数:
setBreathLedArg(uint8_t levelCnt, uint8_t levelUpDevide)//设置呼吸比列 
switchLed1Breath();			//开启LED1呼吸灯
switchLed2Breath();			//开启LED2呼吸灯
startLedBreath();           //开启两个LED灯呼吸效果
stopLedBreath();			//停止两个LED灯呼吸效果    
breathLed();				//执行函数

使用案例
#include <string.h>
#include "board.h"
#include "hal_key.h"
#include "tim-board.h"
#include "timer_handles.h"
#include "led_light.h"  //导入指定的库文件

void Init() {
    BoardInitMcu();
    BoardInitPeriph();
    keys_init();
    setTimer2Callback(Time2Handler);
    Tim2McuInit(1);
    setBreathLedArg(64,128);//设置呼吸比列   参数一:调节亮暗的周期  参数二:调节总时长
    startLedBreath();       //开启两个LED灯呼吸效果
}

int main( void )
{
    Init();
    while( 1 )
    {
		breathLed();   //执行函数  
    }
}:执行函数必须在死循环当中不断执行才能实现呼吸灯的效果开发时如果遇到LED呼吸灯效果只执行一次的需要注意自己的执行函数是否一直放在循环当中不断执行	
    

led灯交替闪烁可参考库文件led_light.c
这里就不过多赘述



二、关于按键函数解析

重点函数(位置在hal_key.c文件下)
使用时需导入#incldue "hal_key.h"
keys_init();//按键初始化
isKey2Pressed();	//判断按键KEY2按下
isKey3Pressed();	//判断按键KEY3按下
isKey4Pressed();	//判断按键KEY4按下
resetKey2();	//清除按键KEY2标志位
resetKey3();	//清除按键KEY3标志位
resetKey4();	//清除按键KEY4标志位

关于keys_init()
实现功能:对按键进行初始化的配置
源码展示
void keys_init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;      

    GPIO_InitStruct.Pin = KEY2_GPIO_PIN;         //在hal_key.h文件当中宏定义的引脚对应着开发板上按键的引脚
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;		 //设置Gpio为浮空输入模式
    GPIO_InitStruct.Pull = GPIO_PULLUP;          //设置Gpio上拉激活
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;  //设置Gpio为高速
    HAL_GPIO_Init(KEY2_GPIO, &GPIO_InitStruct);	//调用hal库当中的 HAL_GPIO_Init将根据指定参数初始化GPIOx外设
    
    //以下按键与KEY2同理
    GPIO_InitStruct.Pin = KEY3_GPIO_PIN;          
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    HAL_GPIO_Init(KEY3_GPIO, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = KEY4_GPIO_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    HAL_GPIO_Init(KEY4_GPIO, &GPIO_InitStruct);
}    

补:当GPIO采用浮空输入模式时,STM32的引脚状态是不确定的,此时STM32得到的电平状态完全取决于GPIO外部的电平状态,所以说在GPIO外部的引脚悬空时,读取该端口的电平状态是个不确定的值。多用于外部按键输入

关于isKeyxPressed();
实现功能:判断按键是否被按下
源码展示(位置:hal_key.c)

volatile char is_key2_down = 0;
volatile char is_key3_down = 0;
volatile char is_key4_down = 0;    
    
char isKey2Pressed(void){
	return is_key2_down;
}

char isKey3Pressed(void){
	return is_key3_down;
}

char isKey4Pressed(void){
	return is_key4_down;
}

void resetKey2(void){
	is_key2_down = 0;
}

void resetKey3(void){
	is_key3_down = 0;
}

void resetKey4(void){
	is_key4_down = 0;
}

#define DEBOUNCE_CNT	2
void scan_keys(void)
{
    static char key2_status = KEY_UP, key2_down_cnt = 0, key2_up_cnt = 0;
    static char key3_status = KEY_UP, key3_down_cnt = 0, key3_up_cnt = 0;
    static char key4_status = KEY_UP, key4_down_cnt = 0, key4_up_cnt = 0;
    char new_status;

    //KEY2
    new_status = HAL_GPIO_ReadPin(KEY2_GPIO, KEY2_GPIO_PIN);
    if((key2_status == KEY_UP) && (new_status == KEY_DOWN)) {
        key2_down_cnt++;
        if(key2_down_cnt >= DEBOUNCE_CNT) {
            is_key2_down = 1;
            key2_status = KEY_DOWN;
        }
    } else {
        key2_down_cnt = 0;
    }

    if((key2_status == KEY_DOWN) && (new_status == KEY_UP)) {
        key2_up_cnt++;
        if(key2_up_cnt >= DEBOUNCE_CNT) {
						is_key2_down = 0;
            key2_status = KEY_UP;;
        }
    } else {
        key2_up_cnt = 0;
    }


    //KEY3
    new_status = HAL_GPIO_ReadPin(KEY3_GPIO, KEY3_GPIO_PIN);
    if((key3_status == KEY_UP) && (new_status == KEY_DOWN)) {
        key3_down_cnt++;
        if(key3_down_cnt >= DEBOUNCE_CNT) {
            is_key3_down = 1;
            key3_status = KEY_DOWN;
        }
    } else {
        key3_down_cnt = 0;
    }

    if((key3_status == KEY_DOWN) && (new_status == KEY_UP)) {
        key3_up_cnt++;
        if(key3_up_cnt >= DEBOUNCE_CNT) {
						is_key3_down = 0;
            key3_status = KEY_UP;;
        }
    } else {
        key3_up_cnt = 0;
    }


    //KEY4
    new_status = HAL_GPIO_ReadPin(KEY4_GPIO, KEY4_GPIO_PIN);
    if((key4_status == KEY_UP) && (new_status == KEY_DOWN)) {
        key4_down_cnt++;
        if(key4_down_cnt >= DEBOUNCE_CNT) {
            is_key4_down = 1;
            key4_status = KEY_DOWN;
        }
    } else {
        key4_down_cnt = 0;
    }

    if((key4_status == KEY_DOWN) && (new_status == KEY_UP)) {
        key4_up_cnt++;
        if(key4_up_cnt >= DEBOUNCE_CNT) {
						is_key4_down = 0;
            key4_status = KEY_UP;;
        }
    } else {
        key4_up_cnt = 0;
    }
}

关于resetKeyx()
实现功能:用于清楚按键标志位
源代码:
void resetKeyx(void){
	is_keyx_down = 0;
}
注意:在调用完isKeyxPressed()时一定要调用resetKeyx()用于清楚对应按键的标志位不然按键无法复用


实现案例
实现功能:按键2按下灯实现亮灭效果
#include <string.h>
#include "board.h"
#include "hal_key.h"
#include "tim-board.h"
#include "timer_handles.h"

void Init() {
    BoardInitMcu();
    BoardInitPeriph();
    keys_init();//按键初始化
    setTimer2Callback(Time2Handler);
    Tim2McuInit(1);
}

void Scan_Key()
{
    if(isKey2Pressed())
    {
		GpioToggle(&Led1);
        resetKey2();	
	}
   
}

int main( void )
{
    Init();
    while( 1 )
    {
		Scan_Key();	
    }
}

三、关于OLED屏函数解析

重点函数()  
导入#incldue "hal_oled.h"
OLED_Init();	//OLED屏初始化
OLED_Clear();	//清屏函数
OLED_Clear_Page(uint8_t page)   //清除行
    
//在指定位置显示一个字符,包括部分字符
//x:0~127
//y:0~63
void OLED_ShowChar(uint8_t x,uint8_t y,uint8_t chr);
    
//显示2个数字
//x,y :起点坐标	 
//len :数字的位数
//size:字体大小
//mode:模式	0,填充模式;1,叠加模式
//num:数值(0~4294967295);	 		  
void OLED_ShowNum(uint8_t x,uint8_t y,uint32_t num,uint8_t len,uint8_t size);
    
//显示num的len个字节的16进制值值
//x,y :起点坐标	 
//len :字节个数
//size:字体大小
//num:数值(0~4294967295);	 		  
void OLED_ShowHex(uint8_t x,uint8_t y,uint32_t num,uint8_t len,uint8_t size);    
 
//显示一个字符号串
//x,y :起点坐标	 
//要显示的字符串
void OLED_ShowString(uint8_t x,uint8_t y,uint8_t *chr);
    
//显示汉字
//x,y :起点坐标	 
//输入oledfont.h下的Hzk数组的第几位,Hzk数组取模了一些开发当中常用到的字符可以对照写入
void OLED_ShowCHinese(uint8_t x,uint8_t y,uint8_t no);
    
//显示汉字
//x,y :起点坐标	 
//取模好的字符数组名
void OLED_ShowCHineseArray(uint8_t x,uint8_t y,char arr[32]);    

//显示图片
//x,y :起点坐标
//width:图片的宽度  height:图片的高度
//取模好的图片数组
void OLED_DrawBMP(unsigned char x, unsigned char y,unsigned char width, unsigned char hight,unsigned char BMP[])
    
使用案例
#include <string.h>
#include "board.h"
#include "hal_key.h"
#include "tim-board.h"
#include "timer_handles.h"
#incldue "hal_oled.h"

void Init() {
    BoardInitMcu();
    BoardInitPeriph();
    keys_init();
    setTimer2Callback(Time2Handler);
    Tim2McuInit(1);
    OLED_Init();  //OLED屏初始化
}

//显示主菜单三个字符,数组由取模软件完成
char zhu[32]={
0x00,0x08,0x08,0x08,0x08,0x08,0x09,0xFA,0x08,0x08,0x08,0x08,0x08,0x08,0x00,0x00,
0x40,0x40,0x41,0x41,0x41,0x41,0x41,0x7F,0x41,0x41,0x41,0x41,0x41,0x40,0x40,0x00
};

char cai[32]={
0x04,0x04,0x44,0xC4,0x4F,0x44,0x44,0xC4,0x24,0x24,0x2F,0xB4,0x24,0x04,0x04,0x00,
0x40,0x44,0x24,0x24,0x15,0x0C,0x04,0xFE,0x04,0x0C,0x15,0x24,0x24,0x44,0x40,0x00
};

char dan[32]={
0x00,0x00,0xF8,0x49,0x4A,0x4C,0x48,0xF8,0x48,0x4C,0x4A,0x49,0xF8,0x00,0x00,0x00,
0x10,0x10,0x13,0x12,0x12,0x12,0x12,0xFF,0x12,0x12,0x12,0x12,0x13,0x10,0x10,0x00
};

//使用取模软件取模二维码
//注:在使用取模软件时要注意把把图片像素最大支持128*64,另存为BMP单色位图格式!!!!
uint8_t erweima[]={
0xFF,0xFF,0x03,0xFB,0xFB,0xFB,0xFB,0xFB,0x03,0xFF,0xFF,0x00,0xC6,0xF7,0xF3,0xFB,
0xFB,0xB6,0xF6,0xF0,0x00,0xFF,0xFF,0x03,0xFB,0xFB,0xFB,0xFB,0xFB,0x03,0xFF,0xFF,
0x37,0x77,0x66,0x36,0xB6,0x86,0x76,0x76,0x66,0xB7,0xF7,0x60,0x86,0xBF,0xBD,0x06,
0x06,0xB1,0xFF,0x6E,0x60,0xE7,0x87,0x66,0xF6,0xB6,0xE6,0xE6,0x06,0xF6,0xF7,0x67,
0xE0,0xEE,0x6E,0x60,0x6F,0x6F,0x6E,0x6E,0x6E,0xED,0xED,0x0C,0x31,0x3F,0x3F,0x8E,
0x8E,0xFF,0xFF,0x66,0xB6,0xFF,0x6D,0xB6,0xFF,0xED,0x3F,0xBF,0xB6,0xFF,0xFF,0x8C,
0xFF,0xFF,0xC0,0xDF,0xDF,0xDF,0xDF,0xDF,0xC0,0xFF,0xFF,0x00,0xDB,0xFB,0x7B,0xCD,
0xCD,0xED,0xFF,0xFB,0x6D,0xFF,0xDB,0xCD,0xDD,0x19,0x7C,0xFF,0xC3,0xEF,0xFF,0xD9
};

int main( void )
{
    Init();
    while( 1 )
    {
		OLED_ShowHex(0,0,1,3,16);		
		OLED_ShowNum(0,2,999,3,16);	
		OLED_ShowString(0,4,(uint8_t*)"LED");
		OLED_ShowCHinese(0,6,29);
		//OLED_ShowCHineseArray(0,0,zhu);
        //OLED_ShowCHineseArray(20,0,cai);
        //OLED_ShowCHineseArray(40,0,dan);
        OLED_DrawBMP(50,2,32,32,erweima);  
        
    }
}

四、关于定时器函数解析

重点函数:
需导入库#include "timer_handles.h"
//定时器2
setTimer2Callback(Time2Handler);
Tim2McuInit(1);//定时器2初始化,单位是1ms
    
//定时器3
setTimer3Callback(Time3Handler);
Tim3McuInit(1);//定时器3初始化,单位是0.25ms  如果要定时1ms则为Tim3McuInit(4); 
    
实例:
实现效果:LED1和LED2一秒定时亮灭 
使用定时器查询方式时在定时器2、定时器3在timer_handles.c源代码文件使用
#include "timer_handles.h"
#include "key_scaner.h"
uint16_t  Time2_time = 1000;   
uint16_t  Time3_time = 1000;
void Time2Handler(){
	keyScanner();
	if(!Time2_time--)      
	{
		Time2_time = 1000;
		GpioToggle(&Led1);
	}
}

void Time3Handler(){
	if(!Time3_time--)
	{
		Time3_time = 1000;
		GpioToggle(&Led2);
	}
}

主函数当中

#include <string.h>
#include "board.h"
#include "hal_key.h"
#include "tim-board.h"
#include "timer_handles.h"


void Init() {
    BoardInitMcu();
    BoardInitPeriph();
    keys_init();//按键初始化
    setTimer2Callback(Time2Handler);   //定时器2的中断回调函数
    Tim2McuInit(1);//定时器初始化,设置定时中断1ms中断一次
    setTimer3Callback(Time3Handler);   //定时器3的中断回调函数
    Tim3McuInit(4);//定时器初始化,单位:0.25ms定时中断1ms中断一次
}


int main( void )
{
    Init();
    while( 1 )
    {
			
    }
}


补:在tim-board.c文件当中有一处定时器中断服务回调函数用户可以把需实现的效果写在上面,由于本人也没有实验过所以这里不过多去描述

在这里插入图片描述

五、关于串口函数解析

重点函数
导入的库文件:#include "usart1-board.h"
    
*功能:初始化串口1
*输入:uint32_t bound,波特率
*输出:无
*返回:无
void USART1_Init(uint32_t bound);


*函数名称:void USART1_SendData(uint16_t Data)
*功能:串口1发送一个字节数据
*输入:uint16_t Data,待发送的数据
*输出:无
*返回:无
void USART1_SendData(uint16_t Data);


*函数名称:uint16_t USART1_ReceiveData(void)
*功能:串口1接收一个字节数据
*输入:无
*输出:无
*返回:返回接收到的串口数据
uint16_t USART1_ReceiveData(void); 


*函数名称:void USART1_SendStr(uint8_t *Data, uint8_t length)
*功能:串口1发送length个字节
*输入:uint8_t *Data-待发送的数据, uint8_t length-待发送的数据长度
*输出:无
*返回:无
void USART1_SendStr(uint8_t *Data, uint16_t length);
 

*函数名称:void USART1_ReceiveClr(void)
*功能:串口1相关寄存器和标志位清空
*输入:无
*输出:无
*返回:无
void USART1_ReceiveClr(void);


*函数:uint16_t USART1_ReadRxBuffer( uint8_t *payload)
*功能:读取USART1接收缓存信息,包括读取接收到的数据长度和缓存数据。
*输入:无
*输出:uint8_t *payload, 指针,指向要用于存放接收缓存的地址
*返回:返回接收到的数据长度
*特殊说明:每调用USART1_ReadRxBuffer()函数,USART1_RX_COUNT会被置0,F_USART1_RX_FINISH赋值为false,
USART1_RX_BUF缓存区会被清0uint16_t USART1_ReadRxBuffer( uint8_t *payload);

uint16_t USART1_RX_COUNT=0;	//接收到的有效字节数目,最大USART1_REC_LEN字节

重定向至串口:
printf();


使用案例:
#include <string.h>
#include "board.h"
#include "hal_key.h"
#include "tim-board.h"
#include "timer_handles.h"
#include "usart1-board.h"         //导入串口库文件

void Init() {
    BoardInitMcu();
    BoardInitPeriph();
    keys_init();
    setTimer2Callback(Time2Handler);
    Tim2McuInit(1);
    USART1_Init(115200);  //初始化串口设置并将波特率设置为115200
}


int main( void )
{
    Init();
    printf("你好");
    while( 1 )
    {
		if(USART1_RX_BUF[0] == 0X0A)	
	    {
            USART1_ReceiveClr();
            GpioWrite(&Led1,0);   
        }else if(USART1_RX_BUF[0] == 0X0B)	
	    {
            USART1_ReceiveClr();
            GpioWrite(&Led1,1);       
        }
    }
}


六、关于传感器函数解析

注:光照,空气质量,可燃气体都是用的ADC协议 温湿度用的是总线协议所以在获取的方式上或有些不同
关于ADC函数
重点函数:
导入的库文件:#include "adc_reader.h"
    
//ADC初始化函数
ADCS_Init();

//获取ADC数值
AdcScanChannel();

//获取电压值
AdcReadCh0();

ADC协议传感器获取案例
#include <string.h>
#include "board.h"
#include "hal_key.h"
#include "tim-board.h"
#include "timer_handles.h"
#include "adc_reader.h"
#include <math.h>
    
void Init() {
    BoardInitMcu();
    BoardInitPeriph();
    keys_init();
    setTimer2Callback(Time2Handler);
    Tim2McuInit(1);
	ADCS_Init();//ADC初始化
}

uint8_t illumination_Oled_Show[10];
uint8_t Air_quality_Oled_Show[10];
uint8_t Combustible_gas_Oled_Show[10];

int main( void )
{
    Init();
    while( 1 )
    {
        //光照
	  	sprintf((char*)illumination_Oled_Show,":%.2f lux",(5/2.0)*(AdcReadCh0()*100));	                         OLED_ShowCHinese(0,0,29);
		OLED_ShowCHinese(20,0,30);
		OLED_ShowString(40,0,illumination_Oled_Show);
		
        
        
        //空气质量
        //sprintf((char*)Air_quality_Oled_Show,":%.2f μg/m3",(float)pow(10,((0.2552-log10((5/AdcReadCh0()-1)/10))/0.5829)));
        //OLED_ShowCHinese(0,2,34);
		//OLED_ShowCHinese(20,2,33);
		//OLED_ShowCHinese(40,2,35);
		//OLED_ShowCHinese(60,2,36);
		//OLED_ShowString(80,2,Air_quality_Oled_Show);
        
        
       //可燃气体
       //sprintf((char*)Combustible_gas_Oled_Show,":%.2f ppm",(float)pow(10,((1.395-log10((50/AdcReadCh0()-20)/10))/0.465))); 
       //OLED_ShowCHinese(0,4,31);
	   //OLED_ShowCHinese(20,4,32);
       //OLED_ShowCHinese(40,4,33);
       //OLED_ShowCHinese(60,4,28);
       //OLED_ShowString(80,4,Combustible_gas_Oled_Show); 
       
        HAL_Delay(1000); //必须写延时 不然会更新太快显示的异常
        
    }
}


关于数字量传感器
数字量传感器(如人体传感器,火焰传感器)相对来说容易很多只需要判断对应引脚的电平即可,因为数字量传感器的值只有01,例如火焰传感器检测到火源时对应引脚会输出高电平这是我们如果要判断他是否有火只需要判断那个引脚的电平就行

使用案例:
#include <string.h>
#include "board.h"
#include "hal_key.h"
#include "tim-board.h"
#include "timer_handles.h"


void Init() {
    BoardInitMcu();
    BoardInitPeriph();
    keys_init();//按键初始化
    setTimer2Callback(Time2Handler);
    Tim2McuInit(1);//定时器初始化,设置定时中断1ms中断一次

}

int main( void )
{
    Init();
    while( 1 )
    {
		//判断人体传感器
        if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_2))    //人体红外传感器的引脚是PA2
		{
			GpioWrite(&Led1,0);
		}
		else
		{
			GpioWrite(&Led1,1);
		}
        
        //判断火焰传感器
        if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0))   //火焰传感器的引脚PA0
		{
			GpioWrite(&Led2,0);
		}
		else
		{
			GpioWrite(&Led2,1);
		}
        
    }
}



继电器与数字量传感器同理也是判断引脚高低电平即可
在开发上会遇到单联继电器和双联继电器会提供两个继电器引脚
分别是PB2和PB0在这里就不过多赘述有疑问可以私聊
 

温湿度获取方式
重点函数:#include "sht3x.h"
导入的库文件:
//温湿度初始化
hal_temHumInit();

//调用方法获取温湿度值
void call_sht11(float *tem_val, float *hum_val);

使用案例

#include <string.h>
#include "board.h"
#include "hal_key.h"
#include "tim-board.h"
#include "timer_handles.h"
#include "sht3x.h"

void Init() {
    BoardInitMcu();
    BoardInitPeriph();
    keys_init();//按键初始化
    setTimer2Callback(Time2Handler);
    Tim2McuInit(1);//定时器初始化,设置定时中断1ms中断一次
    hal_temHumInit();//温湿度初始化
}

float tem,hum;
char tem_data[10]={0};
char hum_data[10]={0};

int main( void )
{
    Init();
    while( 1 )
    {
		call_sht11(&tem,&hum);
        sprintf(tem_data,":%2.2f ℃",tem);
		sprintf(hum_data,":%2.2f RH",hum);
        OLED_ShowString(0,0,(uint8_t *)"Temp");
        OLED_ShowString(0,4,(uint8_t *)"Humi");
        OLED_ShowString(20,0,(uint8_t *)tem_data);
        OLED_ShowString(20,4,(uint8_t *)hum_data);
        HAL_Delay(1000);
    }
}



注意:火焰传感器的引脚(PA0)与adc冲突如果使用引脚的话必须关闭初始化adc

七、Falsh内部读取函数解析

补:Stm32的Flash可实现数据断电存储

重点函数
导入的库文件:#include "flash.h"
*函数:uint32_t STMFLASH_ReadWord(uint32_t faddr)
*功能:读取指定地址的字(32位数据)
*输入:faddr:读地址(此地址必须为2的倍数!!)
*输出:对应数据
*特殊说明:无
uint32_t STMFLASH_ReadWord(uint32_t faddr);



*函数:void STMFLASH_Write(uint32_t WriteAddr,uint32_t *pBuffer,uint32_t NumToWrite)
*功能:读取EEPROM数组写入操作
*输入:WriteAddr:起始地址
	  pBuffer:数据指针
	  NumToWrite:(32)*输出:无
*特殊说明:无
void STMFLASH_Write(uint32_t WriteAddr,uint32_t *pBuffer,uint32_t NumToWrite);



*函数:void WriteFlashTest(uint32_t Addr,uint32_t WriteFlashData)
*功能:读取EEPROM数组写入操作
*输入:WriteAddr:起始地址
	  WriteFlashData:数据
*输出:无
*特殊说明:无
void WriteFlashTest(uint32_t Addr,uint32_t WriteFlashData);


//从指定地址开始读出指定长度的数据
//ReadAddr:起始地址
//pBuffer:数据指针
//NumToWrite:字(32位)数
void STMFLASH_Read(uint32_t ReadAddr,uint32_t *PBuffer,uint32_t NumToRead)


*函数:uint32_t PrintFlashTest(uint32_t FLASH_ADDR)
*功能:读取指定地址的字(32位数据)
*输入:faddr:读地址(此地址必须为2的倍数!!)
*输出:对应数据
*特殊说明:无
uint32_t PrintFlashTest(uint32_t FLASH_ADDR);



使用案例
#include <string.h>
#include "board.h"
#include "hal_key.h"
#include "tim-board.h"
#include "timer_handles.h"
#include "flash.h"
#include "hal_oled.h"

#define Addr_Reserved 0X0800E000                //初始化地址
#define Flash_Data_Len 1						//初始化存储长度	
uint32_t Flash_Data[1];	

void Init() {
    BoardInitMcu();
    BoardInitPeriph();
    keys_init();//按键初始化
    setTimer2Callback(Time2Handler);
    Tim2McuInit(1);//定时器初始化,设置定时中断1ms中断一次
    OLED_Init();
}


int main( void )
{
    Init();
    OLED_ShowString(0,4,(uint8_t *)"Num:");
    STMFLASH_Read(Addr_Reserved,Flash_Data,Flash_Data_Len);
    OLED_ShowNum(20,4,Flash_Data[0],3,16);
    Flash_Data[0]++;
	STMFLASH_Write(Addr_Reserved,(uint32_t*)Flash_Data,Flash_Data_Len);

    while( 1 )
    {
	     
    }
}
 

注意:关于起始地址:Stm32的flash地址起始于0x0800 0000,结束地址是0x0800 0000加上芯片实际的flash大小,不同的芯片flash大小也会不同。

八、关于Lora点对点通信函数解析

重点函数:
导入的库文件:#include "NS_Radio.h" 
           #include "sx1276.h"    
*函数:void NS_RadioInit( uint32_t freq, int8_t power, uint32_t txTimeout, uint32_t rxTimeout)
*功能:对射频模块发送、接收参数进行初始化
*输入:
*			freq载波频率,建议433MHz附近频率最佳
*			power发射功率,最大20
*			txTimeout发送超时时间
*			uint32_t rxTimeout 接收超时时间
*输出:无
*特殊说明:无
void NS_RadioInit( uint32_t freq, int8_t power, uint32_t txTimeout, uint32_t rxTimeout);


*函数:uint16_t ReadRadioRxBuffer( uint8_t *payload)
*功能:读取射频接收缓存信息,包括读取接收到的数据长度和缓存数据。
*输入:无
*输出:uint8_t *payload, 指针,指向要用于存放接收缓存的地址
*返回:返回接收到的数据长度
*特殊说明:每调用一次ReadRadioRxBuffer( )函数,LoRaBufferSize会被置0.
uint16_t ReadRadioRxBuffer( uint8_t *payload);


两种发送数据的方式
//参数1:需要发送的内容 参数2:内容的字节大小
void SX1276Send( uint8_t *buffer, uint8_t size );

//参数1:需要发送的内容 参数2:内容的字节大小
Radio.Send(uint8_t *buffer, uint8_t size);

使用案例:
找机会单独拎出来写


注意事项:进行点对点通信时两个开发板需要插上天线且两个Lora频率要相同开发板上的四个拨码全部往上打
注:本次的使用案例因为时间缘故没有在开发板上烧写,在这里给大家一个参考,案例已经尽量写简单避免出错了,如果烧录后有问题可在评论区踢踢我
  • 14
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: STM32Cube LoRa是STMicroelectronics开发的一种低功耗宽区域网络(LPWAN)技术,它基于LoRaWAN协议,可用于远程传输小量数据的应用。STM32Cube LoRa提供了一套完整的硬件和软件解决方案,使开发者能够快速、灵活地开发出适用于不同物联网应用的LoRaWAN网络设备。 首先,STM32Cube LoRa的硬件部分主要由STMicroelectronics的STM32系列微控制器和SX12xx系列LoRa无线通信模块组成。这些硬件组件具有低功耗、高性能等特点,可在广泛的应用场景中使用。此外,还有一些外设模块和传感器可以与LoRa模块配合使用,提供更丰富的功能。 其次,STM32Cube LoRa的软件部分由STM32Cube软件开发平台和ST-LINK调试工具组成。STM32Cube软件开发平台提供了一套完整的软件库,包括驱动库、中间件和示例代码,可快速开发应用程序。ST-LINK调试工具则提供了对STM32微控制器的在线调试和烧录功能,便于开发者进行调试和测试。 使用STM32Cube LoRa开发LoRaWAN网络设备时,开发者可以选择不同的工具和软件来实现不同的功能。例如,可以使用STM32CubeMX配置工具来生成初始化代码,使用STM32CubeProgrammer进行烧录和调试。此外,还可以使用一些第三方工具和平台来实现数据分析、远程监测等功能,以满足不同应用的需求。 总之,STM32Cube LoRa是一种应用广泛且灵活的LPWAN技术,它提供了一套全面的硬件和软件解决方案,能够帮助开发者快速开发出适用于物联网应用的LoRaWAN网络设备。 ### 回答2: STM32Cube LoRa是一种基于STMicroelectronics的STM32系列微控制器的软件开发平台,专门用于开发和部署LoRa(长距离无线通信技术)应用。这个平台集成了STM32微控制器和Semtech的LoRa收发模块,为开发者提供了丰富的工具和组件,简化了LoRa应用的开发流程。 STM32Cube LoRa包含了一套完整的软件库,其中包括LoRaWAN协议栈,以及用于传输和处理LoRa数据的函数库。开发者可以使用这些库在STM32微控制器上快速实现LoRa通信的功能,无论是作为节点设备还是网关设备。 另外,STM32Cube LoRa还提供了一个集成开发环境(IDE),使开发者可以轻松地编写、编译和调试LoRa应用程序。该IDE还包括了代码生成器、图形化配置工具等,可以帮助开发者快速搭建LoRa网络。 使用STM32Cube LoRa开发者可以快速部署各种LoRa应用,如物联网(IoT)应用、智能城市解决方案等。LoRa技术具有长距离传输、低功耗、低成本等特点,非常适合用于连接远距离的传感器节点和应用。 总之,STM32Cube LoRa是一个强大的开发平台,帮助开发者简化LoRa应用的开发流程,并能够快速部署各种物联网解决方案。 ### 回答3: STM32Cube是意法半导体(STMicroelectronics)推出的一款嵌入式开发工具软件包。它集成了丰富的函数库、驱动程序、配置工具和代码生成器,用于开发STM32微控制器平台上的应用程序。其中,STM32Cube LoRaSTM32Cube软件包中专门用于支持LoRa无线通信协议的一部分。 LoRa是一种低功耗长距离无线通信技术,适用于物联网(IoT)等应用场景中的远程通信。与传统的无线通信技术相比,LoRa具有更长的传输距离和更低的功耗。它基于协议栈的设计和LoRa调制解调技术,可以在低信号强度和高抗干扰环境中实现可靠的通信。 STM32Cube LoRa提供了一套功能丰富的软件库,方便开发者在STM32微控制器上快速实现LoRa通信功能。这个软件包提供了一系列的API,包括LoRa调制解调器、射频配置和管理、数据包传输和接收等。它还提供了示例代码和应用笔记,帮助开发者快速理解和上手LoRa通信技术。 使用STM32Cube LoRa可以有效减少开发时间和开发难度。开发者只需简单配置相关参数即可快速搭建LoRa应用程序,无需从零开始编写复杂的通信协议和底层驱动。同时,该软件包还为开发者提供了直观的图形用户界面,简化了配置和管理LoRa通信模块的过程。 总之,STM32Cube LoRa是一个功能强大的软件包,为开发者提供了丰富的LoRa通信功能支持。它能够极大地简化开发过程,加速LoRa应用的开发和部署。无论是在物联网、智能家居还是其他远程通信场景,STM32Cube LoRa都将为嵌入式开发者带来便利和高效性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值