当前位置: 首页 > article >正文

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

因为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
    在这里插入图片描述

使能定时中断

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

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

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
利用cnt计时
在这里插入图片描述
本质就是将计算 T 公式里的: ARR 代替为 CNT(计数值)—— T = 1 / f = CNT * (PSC + 1) / f

LCD高亮显示

//按键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通信(异步、全双工、字节传输)

配置

在这里插入图片描述

类型转换问题

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

字符与字节

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

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

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串口数据)

主函数
在这里插入图片描述

//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配置

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

代码实现

在这里插入图片描述
在这里插入图片描述


http://www.kler.cn/a/599459.html

相关文章:

  • 借助AI Agent实现数据分析
  • Python虚拟环境:从入门到实战指南
  • 在 ASP.NET Core 中实现限流(Rate Limiting):保护服务免受滥用与攻击
  • ABB机器人更换机器人本体编码器电池的具体步骤
  • 蓝桥杯,冬奥大抽奖
  • 中间件解析漏洞之Tomcat集合
  • 操作系统必知的面试题
  • Maven 构建配置文件
  • 计算机操作系统(四) 操作系统的结构与系统调用
  • 盖泽 寻边器 帮助类
  • C#中状态机Stateless初使用
  • 建库字符集选择`utf8mb4` + `utf8mb4_unicode_ci` 组合
  • 解决 IntelliJ IDEA 方法断点导致程序无法运行的问题
  • python面试高频考点(深度学习大模型方向)
  • 【AndroidRTC-10】webrtc是如何确定双端的编解码类型?
  • C/C++蓝桥杯算法真题打卡(Day10)
  • RAG优化:python从零实现时间管理大师Self-RAG
  • 剑指 Offer II 117. 相似的字符串
  • 网络华为HCIA+HCIP 网络编程自动化
  • C语言字符函数,字符串函数以及内存函数