物联网竞赛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灯的位置以及0或1来控制亮灭,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缓存区会被清0。
uint16_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); //必须写延时 不然会更新太快显示的异常
}
}
关于数字量传感器
数字量传感器(如人体传感器,火焰传感器)相对来说容易很多只需要判断对应引脚的电平即可,因为数字量传感器的值只有0和1,例如火焰传感器检测到火源时对应引脚会输出高电平这是我们如果要判断他是否有火只需要判断那个引脚的电平就行
使用案例:
#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);
使用案例:
找机会单独拎出来写