蓝桥杯物联网——模块熟知

蓝桥杯物联网——模块熟知

1.LED

贴片: LED5 →PC15控制,低电平亮

继电器控制: K1-LED→PA0控制,高电平亮

继电器控制: K2-LED→PA1控制,高电平亮

2.USER摁键

由PC14控制,摁下为0,平时为1(应配为上拉)

长摁与短摁的实现:

unsigned int KEY_flag=0;
uint16_t count=0;

void Key_scan()		//直接将扫描函数丢到定时器里
{
	if(HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_14)==0)			//摁键摁下
	{
		count++;
	}
	if(HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_14)==1)			//摁键松开
	{
		if(count>1&&count<100)	//利用定时器判断摁下时间
		{
			KEY_flag=1;
		}	
		if(count>=100)		//按下经过1s  10*100ms=1s
		{
			KEY_flag=2;
		}
		count=0;
	}
}
void Led_scan()
{
	if(KEY_flag==1)
	{
		HAL_GPIO_WritePin(GPIOC, GPIO_PIN_15, GPIO_PIN_RESET);
	}
	if(KEY_flag==2)
	{
		HAL_GPIO_WritePin(GPIOC, GPIO_PIN_15, GPIO_PIN_SET);
	}
}

3.显示屏OLED

打开参考文件已有初始化函数 void Task_BrdInit(void);将其放在BEGIN与END之间,再配置CubeMX,就不会因为重新生成工程而不见了。
用到最多的无非两个函数sprintf()、OLED_ShowString();啥都ok

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-O4GGVyO5-1650242988004)(4.%E8%93%9D%E6%A1%A5%E6%9D%AF%E7%89%A9%E8%81%94%E7%BD%91%E2%80%94%E2%80%94%E6%A8%A1%E5%9D%97.assets/image-20220214175232026.png)]

①解决显示屏不清位问题(7位变5位多两位不清除)

void OLED_ShowString(uint8_t x, uint8_t y, uint8_t *chr, uint8_t Char_Size)
{										//由函数初始值可知,字符串第一位显示的位置x,也可计算出字符串的长度
    unsigned char j = 0,x1;
	x1=x;								//保存字符串第一位显示的位置x
    while (chr[j] != '\0')
    {
        OLED_ShowChar(x, y, chr[j], Char_Size);
        x += 8;
        if(x > 120)
        {
            x = 0;
            y += 2;
        }
        j++;
    }
    for(j=0;j<x1;j=j+8)				//从第0位到第一位显示的位置x,都用空格显示
    {													//细节:每8位为一个字节的宽度
        OLED_ShowChar(j, y, ' ', Char_Size);
    }
    for(j=x;j<128;j=j+8)			//从字符串最后一位的位置到显示屏能显示的最长位置128,都用空格显示
    {
        OLED_ShowChar(j, y, ' ', Char_Size);
    }
}

②OLED屏显示占用系统教程,影响其他模块灵敏度(比如摁键不灵敏)

if(time_100ms==1)		//使用定时器产生100ms,每隔100ms启动一次显示屏,对其他程序就不会造成影响
{
    OLED_ShowString(0, 0, (unsigned char *)lcdLine_1st_line, 16);
    OLED_ShowString(0, 2, (unsigned char *)lcdLine_2st_line, 16);
    time_100ms=0;		//执行一次之后令定时器重新计时
}

4.矩阵摁键

行:PB6(上)、PB7(下)——这两引脚用来输入
列:PB1(左)、PB0(中)、PA8(右)
其中PA8引脚与显示屏的时钟scl引脚撞了
注意的点:
①GPIO的引脚配置:GPIO_InitStruct.Pull = GPIO_PULLDOWN;{GPIO_ULLUP(上拉)、GPIO_ULLDOWN(下拉)、GPIO_NOPULL(既不上拉也不下拉),这几个参数指的是引脚无操作时保持的状态,上拉高电平,下拉低电平。必须结合摁键扫描来配置}
②部分代码:三处小细节
unsigned int KEY_flag;	//该函数为摁键标志位,须使用extern宏定义

void key_scan()			//此函数利用定时器10ms消抖,不再使用额外消抖
{
	HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_SET);
	HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET);
	if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_6))
		KEY_flag=11;
	if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7))
		KEY_flag=21;

	HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET);
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET);
	if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_6))
		KEY_flag=12;
	if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7))
		KEY_flag=22;

	HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET);
	if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_6))
		KEY_flag=13;
	if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7))
		KEY_flag=23;
}

void Led_scan()			//执行函数,什么摁键执行命令
{
	if(KEY_flag==11)
	{
		HAL_GPIO_WritePin(GPIOC, GPIO_PIN_15, GPIO_PIN_SET);
	}
	if(KEY_flag==21)
	{
		HAL_GPIO_WritePin(GPIOC, GPIO_PIN_15, GPIO_PIN_RESET);
	}
}

----------------------------------------------------------------------------------------------------
main函数里的调用:
 if(time_10ms==1)	//此处用定时器定时10ms
     key_scan();
	Led_scan();
③如果没用到B3,B6键,就别开,会有延时影响。

5.ADC

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hvKawHz2-1650242988005)(4.%E8%93%9D%E6%A1%A5%E6%9D%AF%E7%89%A9%E8%81%94%E7%BD%91%E2%80%94%E2%80%94%E6%A8%A1%E5%9D%97.assets/image-20220214180429857.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-M5yx2CdJ-1650242988005)(4.%E8%93%9D%E6%A1%A5%E6%9D%AF%E7%89%A9%E8%81%94%E7%BD%91%E2%80%94%E2%80%94%E6%A8%A1%E5%9D%97.assets/image-20220222182649799.png)]

注意:配置完初始状态,要将ADC中断打开(ADC也有中断!)

用到无非三个函数:

for(i=0;i<=1;i++)
{
	HAL_ADC_Start(&hadc);		//启动ADC
 if(HAL_ADC_PollForConversion(&hadc,100)==HAL_OK)	//等待转换完成,延时时间100ms
	ad[i]=HAL_ADC_GetValue(&hadc)*(3.3/4095);	//获取AD数值(0-4095),需要转为电压值。
}	//获取一个通道AD值,再次循环可获得第二个通道

6.温度传感器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gi5mJ3nU-1650242988006)(4.%E8%93%9D%E6%A1%A5%E6%9D%AF%E7%89%A9%E8%81%94%E7%BD%91%E2%80%94%E2%80%94%E6%A8%A1%E5%9D%97.assets/image-20220214180540002.png)]

7.RTC时钟

在STM32CubeMX中找到RCT,

勾选两项:Activate Clock Source(激活时钟)、Activate Calendar(激活日历)

设置同步预分频——307

使用十进制

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EgYfK0vd-1650242988007)(4.%E8%93%9D%E6%A1%A5%E6%9D%AF%E7%89%A9%E8%81%94%E7%BD%91%E2%80%94%E2%80%94%E6%A8%A1%E5%9D%97.assets/image-20220222191155901.png)]

8.外部中断

只需在stm32l0xx_it.c文件中找到HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_10)中断函数并进入其定义,即可找到回调函数HAL_GPIO_EXTI_Callback(GPIO_Pin)

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)	//中断回调函数
{
	if(GPIO_Pin==GPIO_PIN_10)	//判断中断是哪个引脚产生的,严谨性
	{
		;
	}
}

9.定时器中断

1.普通定时器(TIM6,TIM7)

①配置

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lwoEHleo-1650242988008)(4.%E8%93%9D%E6%A1%A5%E6%9D%AF%E7%89%A9%E8%81%94%E7%BD%91%E2%80%94%E2%80%94%E6%A8%A1%E5%9D%97.assets/image-20220315222302950.png)]

定时器的计算公式:T=(arr+1)*(psc+1)/CLK。其中,CLK是MCU的时钟频率,arr和psc分别为自动重装载值和预分频系数。
比如定时1毫秒,假设时钟频率为32MHZ,只需要设定arr和psc分别为999和31就可以了。计算如下:1ms=(31+1)*(999+1)/32MHZ。值得注意的是,arr和psc分别为31和999也可以
②代码
只用到两个函数即可HAL_TIM_Base_Start_IT(&htim6) 与 void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
HAL_TIM_Base_Start_IT(&htim6) 函数:放在while循环前即可使能定时器
→在stm32l0xx_hal_tim.c文件里,搜索start即可找到该函数
HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)函数:定时器回调函数,放在main函数外
→在stm32l0xx_hal_tim.c文件里,搜索==__weak==即可找到该函数(多找几下就有了)

2.通用定时器(TIM2,TIM3),一般只用来输出PWM

①配置

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TBJPCDfw-1650242988008)(4.%E8%93%9D%E6%A1%A5%E6%9D%AF%E7%89%A9%E8%81%94%E7%BD%91%E2%80%94%E2%80%94%E6%A8%A1%E5%9D%97.assets/QQ%E6%88%AA%E5%9B%BE20220329194902.png)]

②代码
只用到两个函数即可HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_3) 与 __HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_2,500);
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_3)函数:放在while函数之前即可使能PWM
→在stm32l0xx_hal_tim.c文件里,搜索PWM即可找到该函数
__HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_3,500)函数:用做比较PWM输出,其中500与重装载值999的比值,就是输出PWM的占空比
→在stm32l0xx_hal_tim.c文件里,搜索compare即可找到该函数

10.串口

①因为存在系统CPU占用过多,所以直接使用DMA传输(既可以省系统时间,也可以忽略数据量过大)

②一般使用空闲中断接收数据(既可以确定长度也可以不定长度的数据)

③DMA配置细节,一般只配置输入单片机(rx)的DMA,不配置输出(tx)。因为DMA不能同时双向传输,本身串口也不是全双工。

//	main函数里的初始化
__HAL_UART_CLEAR_IDLEFLAG(&huart2);	
__HAL_UART_ENABLE_IT(&huart2, UART_IT_IDLE);
HAL_UART_Receive_DMA(&huart2,reply,50);

void rx2(void)		//需将rx2()放在void USART2_IRQHandler(void)串口中断函数里
{
	if(RESET != __HAL_UART_GET_FLAG(&huart2, UART_FLAG_IDLE))   //判断是否是空闲中断
	{
		__HAL_UART_CLEAR_IDLEFLAG(&huart2); 		//清除空闲中断标志(否则会一直不断进入中断)
		HAL_UART_DMAStop(&huart2);   
        uart_flag=1;		//设置串口已接收的标志位
   		HAL_UART_Receive_DMA(&huart2,reply,50);		//重启开始DMA传输 每次255字节数据
	}
}

11.CRC校验

找到CRC,勾选,keil里调用函数使用就行了。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CFRXMy9u-1650242988009)(4.%E8%93%9D%E6%A1%A5%E6%9D%AF%E7%89%A9%E8%81%94%E7%BD%91%E2%80%94%E2%80%94%E6%A8%A1%E5%9D%97.assets/image-20220214174928266.png)]

常用函数

①对变量进行处理

sprintf()函数:数字变字符串

char lcdLine_1st_line[16];

sprintf(lcdLine_1st_line, “%f”,tem);

tem为数字,sprintf()的作用为把数字转为char类型的字符串

sscanf()函数:字符串变数字

① sscanf( (char *)rx,“%d-%d-%d”,&h,&m,&s); //将字符串转数字

② sscanf(“654321abcdedfABCDEF”, “%[1-9a-z]”, str); //取仅包含指定字符集的字符串
printf(“str=%s\n”, str); //str=654321abcded,只取数字和小写字符

③ sscanf("zhoue3456 ", “%4s”, str); //取指定长度的字符串
printf(“str=%s\n”, str); //str=“zhou”;

④ sscanf(“BCDEF123456abcdedf”, “%[ ^ a-z]”, str); //取到指定字符集为止的字符串

​ printf(“str=%s\n”, str); // str=BCDEF123456, 取遇到大写字母为止的字符串

strlen()函数:测量字符串实际长度(不包含‘\0’)

char b[]=“love”;

printf(“%ld\n”,strlen(b)); //结果为4

strcat()函数:字符串拼接

adc=strcat(lcdLine_1st_line," ");

adc=strcat(adc,lcdLine_2st_line);

也可自己写:
char a[100]="123",b[]="321",c;
unsigned int i,i1,i2;
i1=strlen(a);
i2=strlen(b);
for(i=0;i<=i2-1;i++)
{
	   a[i+i1]=b[i];
}
printf("%s",a);		//输出123321
sizeof()函数:测量字符串字节大小——所占内存(一般用不到)

unsigned int lon;

char lcdLine_1st_line[16];

lon=sizeof(lcdLine_1st_line);

sizeof()的作用是测量字符串包含的字符个数。

②位运算

aba&b(且)a|b(或)a^b(异或)~a(位反)!a(值反)
0000010
0101110
1001100
1111000
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值