收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。
需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人
都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
else
{
key[i].jude_sta=0;
}
}
break;
case 2:
{
if(key[i].key_sta==1)
{
key[i].jude_sta=0;
}
}
break;
}
}
}
}
key.h文件
#ifndef __KEY_H
#define __KEY_H
#include “main.h”
#include “stdbool.h”
struct keys
{
bool key_sta;
char jude_sta;
bool key_flog;
};
#endif /*__KEY_H*/
### 2.长按键(按压时间>70ms)
.c文件
#include “key_chang.h”
struct key_chang keys_chang[4]={0};
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance==TIM1)
{
keys_chang[0].key_chang_sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);
keys_chang[1].key_chang_sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
keys_chang[2].key_chang_sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2);
keys_chang[3].key_chang_sta=HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);
for(char i=0;i<4;i++)
{
switch (keys_chang[i].jude_sta)
{
case 0:
{
if(keys_chang[i].key_chang_sta==0)
{
keys_chang[i].jude_sta=1;
keys_chang[i].key_chang_time=0;
}
}
break;
case 1:
{
if(keys_chang[i].key_chang_sta==0)
{
keys_chang[i].jude_sta=2;
}
else
{
keys_chang[i].jude_sta=0;
}
}
break;
case 2:
{
if(keys_chang[i].key_chang_sta==1)
{
keys_chang[i].jude_sta=0;
if(keys_chang[i].key_chang_time<70)
{
keys_chang[i].key_flog=1;
}
}
else
{
keys_chang[i].key_chang_time++;
if(keys_chang[i].key_chang_time>70)
{
keys_chang[i].key_chang_flog=1;
}
}
}
break;
}
}
}
}
.h文件
#ifndef __KEY_CHANG_H
#define __KEY_CHANG_H
#include “main.h”
#include “stdbool.h”
struct key_chang
{
char jude_sta;
bool key_chang_sta;
bool key_chang_flog;
uint16_t key_chang_time;
bool key_flog;
};
#endif /*__KEY_CHANG_H*/
### 3 .双击按键(针对短按键)
.c文件
#include “key_shuang.h”
struct key_chang keys_chang[4]={0};
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance==TIM1)
{
keys_chang[0].key_chang_sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);
keys_chang[1].key_chang_sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
keys_chang[2].key_chang_sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2);
keys_chang[3].key_chang_sta=HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);
for(char i=0;i<4;i++)
{
switch (keys_chang[i].jude_sta)
{
case 0:
{
if(keys_chang[i].key_chang_sta==0)
{
keys_chang[i].jude_sta=1;
keys_chang[i].key_chang_time=0;
}
}
break;
case 1:
{
if(keys_chang[i].key_chang_sta==0)
{
keys_chang[i].jude_sta=2;
}
else
{
keys_chang[i].jude_sta=0;
}
}
break;
case 2:
{
if((keys_chang[i].key_chang_sta==1)&&(keys_chang[i].key_chang_time<70))
{
if(keys_chang[i].key_shuangclick_num==0)
{
keys_chang[i].key_shuangclick_num=1;
keys_chang[i].key_shuangclick_time=0;
}
else
{
keys_chang[i].key_shuangclick_flog=1;
keys_chang[i].key_shuangclick_num=0;
}
keys_chang[i].jude_sta=0;
}
else if((keys_chang[i].key_chang_sta==1)&&(keys_chang[i].key_chang_time>=70))
{
keys_chang[i].jude_sta=0;
}
else
{
if((keys_chang[i].key_chang_time>=70))
{
keys_chang[i].key_chang_flog=1;
}
keys_chang[i].key_chang_time++;
}
}
break;
}
if(keys_chang[i].key_shuangclick_num==1)
{
keys_chang[i].key_shuangclick_time++;
if(keys_chang[i].key_shuangclick_time>35)
{
keys_chang[i].key_flog=1;
keys_chang[i].key_shuangclick_num=0;
}
}
}
}
}
.h文件
#ifndef __KEY_SHUANG_H
#define __KEY_SHUANG_H
#include “main.h”
#include “stdbool.h”
struct key_chang
{
char jude_sta;
bool key_chang_sta;
bool key_chang_flog;
uint16_t key_chang_time;
bool key_flog;
uint16_t key_shuangclick_num;
uint16_t key_shuangclick_time;
bool key_shuangclick_flog;
};
#endif
**注意:结构体在main.c中调用时要extern声明,且还要打开定时器中断:
HAL\_TIM\_Base\_Start\_IT(&htim1)**
## 四.pwm波的输出
### 1.cubeMX配置

其中用到的定时器,要根据实际情况选择,
周期T=(psc+1)\*ARR/内部时钟,其中的占空比由ARR来决定的,一般ARR设置为100,方便占空比的计算。
要开HAL\_TIM\_PWM\_START(&htimx,TIM\_CHANNEL\_X)
若要改变占空比,\_\_HAL\_TIM\_SetCompara(&htimx,TIM\_CHANNEL\_X,占空比值),对其占空比进行设置
**具体情况要根据题目来**.
## 五 .输入捕获

### 1 .原理
是对要捕获的波进行频率,占空比的测量,实质时,对要捕获的波进行**掐时** ,在上升沿处掐时,可以算频率,在下降沿掐时可以算占空比,一个注意的地方:**在配置输入捕获时要配置PSC与ARR(相当于定时器)其一个周期一定要大于要捕获的波的周期(一般大两倍),放置捕获不完全,换句话说,如果小了,当波的下一个上升沿还未到来时,我的计数时间已经从新从0开始了,必然造成错误**
### 2 .cubeMX配置


### 3 .代码
将其放在按键的.c文件中
/********************输入捕获************************/
double frequency;
uint16_t duty_cycle;
double frequency_jishuan;
uint16_t duty_cycle_jishuan;
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) //输入捕获回调函数
{
if(htim->InstanceTIM3)
{
if(htim->ChannelHAL_TIM_ACTIVE_CHANNEL_1)//通道检测
{
frequency=HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_1); //获取通道一的直接测量值,用于计算频率
duty_cycle=HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_2);//获取通道二的直间接量值,用于计算占空比
\_\_HAL\_TIM\_SetCounter(htim,0);//清零计数值
frequency_jishuan=(80000000/80)/frequency;//计算频率
duty_cycle_jishuan=(duty_cycle/frequency)\*100;//计算占空比,因为占空比就等于上升沿的计数值比上整个周期的值再乘以100
HAL\_TIM\_IC\_Start(htim,TIM_CHANNEL_1);//开启通道一
HAL\_TIM\_IC\_Start(htim,TIM_CHANNEL_2);//开启通道二
}
}
}
主函数初始化两个通道:
HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_1);//计算频率的通道
HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_2);//计算高电平时间的通道
## 六 .ADC
### 1 .cubeMX的配置
配置比较简单

### 2 .代码
.c文件
#include "bsp_adc.h "
float getADC(ADC_HandleTypeDef *pin)
{
uint16_t adc;
HAL_ADC_Start(pin); //开启adc通道
adc = HAL_ADC_GetValue(pin); // 获取adc读出返回的值
return adc*3.3/4096; //转换成0~3.3V的电压,因为我们的ADC2是12bit,也就是2的12次方,所以要除以4096
}
.h文件
#ifndef __BSP_ADC_H
#define __BSP_ADC_H
#include “main.h”
float getADC(ADC_HandleTypeDef *pin);
#endif
## 七 .IIC读写EEPROM
### 1 . cubeMX配置

把PB6、PB7的GPIO配置成输出模式即可

然后导入官方资料包给的IIC文件

### 2 .代码
在导入的.c文件后面加入下面代码,记得.h文件中声明
void eeprom_write(unsigned char arr,unsigned char dat)
{
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(arr);
I2CWaitAck();
I2CSendByte(dat);
I2CWaitAck();
I2CStop();
}
unsigned char eeprom_read(unsigned char dat)
{
unsigned char datt;
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(dat);
I2CWaitAck();
I2CStop();
I2CStart();
I2CSendByte(0xa1);
I2CWaitAck();
datt = I2CReceiveByte();
I2CWaitAck();
I2CStop();
return datt;
}
我们的EEPROM一个数据存放单元只能存放一个字节的数据
如果需要存入一个int(两个字节)类型的数据,需要分开存放进行写入,注意写入需要一定的时间,因此需要进行一个10ms的延时
读的时候需要进行位操作,把第一个字节的数据移到高八位,再与上我们的低八位即可
写:
read_count1 = eeprom_count >> 8;
read_count2 = eeprom_count&0xff;
eeprom_write(1,read_count1);
HAL_Delay(10);
eeprom_write(2,read_count2);
读:
eeprom_count = (eeprom_read(1)<<8) + eeprom_read(2);
## 八 .串口通信
### 1.cube
配置波特率以及开启中断.


### 2.代码
串口的接收:
char data[30];
char rx;
uchar rx_flag;
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
data[rx_flag++] = rx;
HAL\_UART\_Receive\_IT(&huart1,&rx,1);
}
**主函数声明一下:HAL\_UART\_Receive\_IT(&huart1,&rx,1);**
接收例子:
void uart_porc(void)
收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。
需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人
都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
rt)
{
data[rx_flag++] = rx;
HAL\_UART\_Receive\_IT(&huart1,&rx,1);
}
**主函数声明一下:HAL\_UART\_Receive\_IT(&huart1,&rx,1);**
接收例子:
void uart_porc(void)
收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。
[外链图片转存中…(img-Y6nLoAoj-1715798919195)]
[外链图片转存中…(img-ZfliNg78-1715798919195)]
需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人
都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!