蓝桥杯——嵌入式学习日记

因为lED和LCD共用PC8~PC15引脚,要通过锁存(LE)和(GPIOC->ODR)来避免LED和LCD引脚冲突

修改点:

  • main.c中,GPIO初始化引脚后,LE(PD2引脚低电平锁存,退出透明模式,LCD的输出就无法影响LED引脚的状态)
  • LCD_DisplayStringLine();

  • LCD_Clear()

定时器中断

定时器功能

定时器频率和周期公式

  • PSC(预分频系数): 1 / f == T, 乘上(PSC+1) 得到执行一次累加操作的实际周期,再乘上(ARR+1)等于中断周期
  • 预分频理解: 假设原本1ms执行一次累加, PSC == 2, 则当前变成2ms才执行一次累加(另外的1ms分给了别的任务)
  • 时钟配置
    - 通过STM32CubeMX,配置TIM2(通用定时器)的参数(Fsystem = 80MHz = 80 000 000)
    假设定时中断周期要求 1s , 则 ARR+1=8000 , PSC+1 = 10000

使能定时中断

c 复制代码
//定时中断需要使能
   HAL_TIM_Base_Start_IT(&htim2);  //HAL_TIM_Base_Start_IT函数用于以中断模式启动定时器

长按键、短按键(使用TIM3)



利用cnt计时

本质就是将计算 T 公式里的: ARR 代替为 CNT(计数值)------ T = 1 / f = CNT * (PSC + 1) / f

LCD高亮显示

c++ 复制代码
//按键4通过循环取余数,控制lcd某行高亮显示
static uint16_t temp_line = 0;
void Hight_light_lcd_line(){
     
	key_s4 = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0);

	if(key_s4==RESET && k4_last_state==SET){  //按下B4
	    temp_line++;
		temp_line%=3;
		HAL_Delay(200);
	}
	
	//控制功能栏轮流高亮显示
	if(temp_line==0){
	   
       //sprintf();   用于写入字符串到字符数组
	   LCD_SetBackColor(Red);  //该行以下的背景颜色是红色
	   sprintf(text, "    Hello, Vodka!     ");
	   LCD_DisplayStringLine(Line3, (uint8_t*) text );
		
	   LCD_SetBackColor(Black);		//该行以下的背景颜色是黑色
	   sprintf(text, "      Count: %d        ", Count);
	   LCD_DisplayStringLine(Line4, (uint8_t*) text);
	   
		
	   sprintf(text, "   LightMode: %d        ", lightMode);
	   LCD_DisplayStringLine(Line5, (uint8_t*) text);

	}
	else if(temp_line==1){
	   //sprintf();   用于写入字符串到字符数组
	   sprintf(text, "    Hello, Vodka!     ");
	   LCD_DisplayStringLine(Line3, (uint8_t*) text );
		
	   LCD_SetBackColor(Red);	
	   sprintf(text, "      Count: %d        ", Count);
	   LCD_DisplayStringLine(Line4, (uint8_t*) text);
	   LCD_SetBackColor(Black);	
		
	   sprintf(text, "   LightMode: %d        ", lightMode);
	   LCD_DisplayStringLine(Line5, (uint8_t*) text);	
	}
    else if(temp_line==2){
	   //sprintf();   用于写入字符串到字符数组
	   sprintf(text, "    Hello, Vodka!     ");
	   LCD_DisplayStringLine(Line3, (uint8_t*) text );
		
	   sprintf(text, "      Count: %d        ", Count);
	   LCD_DisplayStringLine(Line4, (uint8_t*) text);
	   
	   LCD_SetBackColor(Red);	
	   sprintf(text, "   LightMode: %d        ", lightMode);
	   LCD_DisplayStringLine(Line5, (uint8_t*) text);
	   LCD_SetBackColor(Black);	
	}
	//LED闪烁,间隔两秒闪烁一次
	light_led(3,lightMode%2);
   
}

PWM波形

原理

占空比:高电平持续时间占整个周期时长的比值
PWM频率和占空比的概念:占空比由捕获比较寄存器(CCR)决定,而频率由ARR和PSC共同决定。不同的PSC和ARR组合可以得到相同的频率,只要它们的乘积相同。例如,PSC=1和ARR=1000,与PSC=2和ARR=500,得到的频率是一样的,但占空比的调节范围可能不同,因为ARR的值不同。

CubeMX配置

初始化

CCR(输出比较寄存器)

输入捕获测量引脚输出PWM波形

通过计算两个中断之间CNT差值(capture_value),得出中断周期(捕获周期)

捕获周期计算公式

信号发生器

PWM输出引脚和输入捕获引脚,板子上的引脚R37~R40分别是:电压采集1、电压采集2、频率输出1(PB4)、频率输出2(PA15)

例题


TIM17配置(记得配置NVIC)

pwm输入捕获代码

PA1、PA7需要杜邦线连接; PA1配置TIM2的通道2、PA7配置TIM17的通道1

输入捕获555定时器的频率

时钟通道配置

引脚PA15和引脚PB4测量频率输入1和频率输入2

代码

TIM2、TIM16输入捕获中断开启

TIM2、TIM16输入捕获展示

ADC测量

配置ADC1和ADC2

代码实现

USART通信(异步、全双工、字节传输)

配置

类型转换问题

c++ 复制代码
字符类型(char)在算术运算中会被转换为整数类型(int)。
short型会被转换为int型。
float型会被转换为double型以提高精度。
当有符号数与无符号数进行运算时,所有操作数自动转换为无符号类型

字符与字节

存储字符串 "bens in 2023/23/23" 的 char 数组需占用 19 字节,空格也算字符,包含'\0'作为终止符(转义字符\n,\t也算字符)

代码实现(向上位机发送数据)

c++ 复制代码
void UART_Tx_Test(void){
   
   sprintf((char*)uart_tx_text,"Hey~ Vodka~\r\n");	
   HAL_UART_Transmit(&huart1, (uint8_t *)uart_tx_text, strlen(uart_tx_text), 50);  //超时时间限制为50ms
   HAL_Delay(2000); //发送数据间隔时间: 0.1s	
	
}

代码实现(按字节循环接收uart串口数据)

主函数

c++ 复制代码
//util.h
#ifndef __util_h
#define __util_h
//串口接收变量
extern char uart_rx_text[22];
extern uint8_t Rx_Byte;
extern uint8_t Rx_Index;
extern uint8_t Rx_DoneFlag;

//车辆信息(串口接收)
extern char car_type[5];
extern char car_data[5];
extern char car_time[13];

//测试函数                                      
void lcd_test(void);                            
                                                                                            
//ADC测量                                       
void ADC_show(void);                            
	
//ADC测量电压
void ADC_Caculate_Volt(void);

//串口发送测试
void UART_Tx_Test(void);

//串口接收测试(只能通过中断接收)
void UART_Rx_Test(void);

//UART中断数据后续处理(放在主程序里循环)
void uart_data_process(void);
	
#endif


//util.c
//UART中断回调接收数据(第一次中断在主函数)
void HAL_UART_RxCpltCallback(UART_HandleTypeDef * huart){
    if(huart->Instance == USART1){
		uart_rx_text[Rx_Index++] = Rx_Byte;
		//判断接收的字节是否完成
   		if(Rx_Index==22||Rx_Byte=='\n'){
		    Rx_DoneFlag = 1;
		}
		//继续开启下一次中断
		HAL_UART_Receive_IT(&huart1,&Rx_Byte,sizeof(Rx_Byte));
	}
}

//UART中断数据后续处理(放在主程序里循环)
void uart_data_process(void){
   //判断中断接收完毕标志
   if(Rx_DoneFlag==1){
      if(Rx_Index <= 22){   //接收数组长度22字节,除去\0,实际只能存储21个字节
	     sscanf(uart_rx_text, "%4s %4s %10s", car_type, car_data, car_time);
		 //展示数据
		 LCD_SetBackColor(Yellow);
         LCD_SetTextColor(Black);		
		  
          sprintf(rx_display_text,"        UART_Rx           ");
		  LCD_DisplayStringLine(Line0,rx_display_text);		  
		  
		  sprintf(rx_display_text,"    car_type:%s       ",car_type);
		  LCD_DisplayStringLine(Line1,rx_display_text);
		  
		  sprintf(rx_display_text,"    car_data:%s         ",car_data);
		  LCD_DisplayStringLine(Line2,rx_display_text);
		  
		  sprintf(rx_display_text," car_time:%s        ",car_time);
		  LCD_DisplayStringLine(Line3,rx_display_text);		  
	  }
	  else{
	     sprintf(rx_display_text,"        Rx_Error\r\n          ");
		 HAL_UART_Transmit(&huart1, (uint8_t*)rx_display_text, strlen(rx_display_text), 50); 
	  }
	  //重置相应标志
	  Rx_DoneFlag = 0;
	  Rx_Index = 0;
	  memset(uart_rx_text,0,strlen(uart_rx_text));
   }
}

通过定时器,UART串口接收不定长的数据

原理

传送一个字节花费的时间,转化为CNT的值来判断

间隔指定时间读取一个数据

判断结束的标志:最后一个位的时间大于1.5ms

配置

TIM4:内部时钟、波特率:9600、 开启中断、 PSC: 8000-1

串口中断开启、时钟使能

中断处理、中断回调


自行编写




IIC

IIC原理图

非易失性存储器

从机地址

读写位:1是读、2是写

代码实现


RTC实时时钟

设置(读取)时间、日期,设置闹钟

RTC配置


代码实现


相关推荐
每次的天空1 小时前
移动应用开发:自定义 View 处理大量数据的性能与交互优化方案
android·java·学习·交互
咚咚轩1 小时前
蓝桥杯15届国赛 最小字符串
蓝桥杯
海尔辛1 小时前
学习黑客光猫-路由器-交换机
网络·学习·智能路由器
5649832 小时前
逆向工程学习记录:反汇编反编译
学习
Kazefuku2 小时前
Excel学习笔记
笔记·学习·excel
小浪学编程3 小时前
C#学习——继承、封装、多态
学习
hnlucky3 小时前
《Zabbix Proxy分布式监控实战:从安装到配置全解析》
数据库·分布式·学习·adb·zabbix·集成学习·proxy模式
red_redemption3 小时前
自由学习记录(59)
学习
Chef_Chen4 小时前
从0开始学习大模型--Day04--大模型的框架以及基本元素
学习
小白聊AI4 小时前
什么是AI写作
人工智能·学习·ai写作