新大陆STM32开发Lora通用库函剖析_lora库函数(1)

} 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文件当中有一处定时器中断服务回调函数用户可以把需实现的效果写在上面,由于本人也没有实验过所以这里不过多去描述


![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/2fc023f894a14f57973e30bf2857b5c9.jpeg)


### 五、关于串口函数解析



重点函数
导入的库文件:#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:数据
*输出:无

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年嵌入式&物联网开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新!!

长且无助。**

因此收集整理了一份《2024年嵌入式&物联网开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

[外链图片转存中…(img-eb5yWt1z-1715745251612)]

[外链图片转存中…(img-hhNoMFZw-1715745251612)]

[外链图片转存中…(img-JGWudK0h-1715745251613)]

[外链图片转存中…(img-XDEjk0By-1715745251613)]

[外链图片转存中…(img-Qbw07CGb-1715745251614)]

[外链图片转存中…(img-yy1Kasys-1715745251615)]

[外链图片转存中…(img-A3EeX96u-1715745251615)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新!!

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值