蓝桥杯嵌入式

蓝桥杯嵌入式

考点

image-20241207162736049

image-20241207162715155

时钟RCC__HSEz

image-20241207104425400

输入24MHz的HSE通过PLL锁相环输出80MHz

image-20241207104450012

LED:LD1~8 ---PC8~15,低电平电亮

锁存器LE:PD2,=1选通,=0锁存

先将锁存器LE引脚初始化为低电平,锁存LED状态,需要操作LED时再开启,操作完即关闭,避免LED与LCD的互相影响

image-20241207153800382

image-20241201155549021

key:

从上到小,按键B1~4,

PB0~2,PA0,上拉,检测低电平

移植LCD:

不需要再CubeMX中进行引脚配置

将下类文件添加进工程文件夹

image-20241207160808608

main中只用声明lcd.h头文件就可以使用LCD

串口通信

UART1(9600)

PA9,10(需手动配置,默认为PC端口)

异步模式:

开启串口中断

添加的头文件

>stdio.h(标准输入输出头文件)

stdio.h头文件中包含了以下几类函数:

  1. 输入输出函数
    • printf:格式化输出函数,用于将数据输出到标准输出(通常是屏幕)。
    • scanf:格式化输入函数,用于从标准输入(通常是键盘)读取数据。
    • fopen:打开文件。
    • fclose:关闭文件。
    • fread:从文件中读取数据。
    • fwrite:向文件中写入数据。
    • fgets:从文件中读取一行数据。
    • fputs:向文件中写入一行数据。
  2. 文件操作函数
    • remove:删除文件。
    • rename:重命名文件。
    • tmpfile:创建临时文件。
    • tmpnam:生成临时文件名。
  3. 控制函数
    • setbuf:设置缓冲区。
    • setvbuf:设置缓冲区。
    • getchar:从标准输入读取一个字符。
    • putchar:向标准输出写入一个字符。

>string.h(字符串处理头文件)

string.h头文件中包含了以下几类函数:

  1. 字符串操作函数
    • strlen:计算字符串的长度。
    • strcpy:复制字符串。
    • strncpy:复制字符串的一部分。
    • strcat:连接两个字符串。
    • strncat:连接两个字符串的一部分。
    • strcmp:比较两个字符串。
    • strncmp:比较两个字符串的一部分。
    • strchr:查找字符串中首次出现的字符。
    • strrchr:查找字符串中最后一次出现的字符。
    • strstr:查找子字符串。
    • strtok:分割字符串。
  2. 内存操作函数
    • memcpy:复制内存块。
    • memmove:移动内存块。
    • memcmp:比较内存块。
    • memset:设置内存块。
  3. 字符操作函数
    • isalpha:检查字符是否为字母。
    • isdigit:检查字符是否为数字。
    • islower:检查字符是否为小写字母。
    • isupper:检查字符是否为大写字母。
    • isspace:检查字符是否为空白字符。
    • toupper:将字符转换为大写。
    • tolower:将字符转换为小写。

声明串口句柄

UART_HandleTypeDef huart1;

因为CubeMX中自动生成了串口初始化,并包含在MX_GPIO_Init()中,故不用再次初始化

设置串口

串口发送

sprintf(str, "%04d:Hello,world.\r\n", counter);//**格式化字符串**
HAL_UART_Transmit(&huart1,(unsigned char *)str, strlen(str), 50);//**通过UART发送字符串**

串口接收

main():

HAL_UART_Receive_IT(&huart1, rx, 1);//启动接收中断。
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)//串口接收回调函数(弱函数)
{
	GPIOC->ODR = ((rx[0]  <<  8) | 0x00FF);//将接收到的二进制数据写入C端口,控制LED
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);//1选通锁存器
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);	//0	锁存
	HAL_UART_Receive_IT(&huart1, rx, 1);
}

ADC测量

image-20241206225840867

PB15__J11 电压采集1 ADC2_IN15

PB12__J12 电压采集2 ADC1_IN11

image-20241207104134156

image-20241207104246397

image-20241207104258941image-20241207104314183

不用设置NVIC

image-20241207104346097

获取ADC数值函数:

uint16_t getADC2_PB15_VL1(void)//PB15--ADC2_IN15
{
	uint16_t adc = 0;
	HAL_ADC_Start(&hadc2);//开启ADC2
	adc = HAL_ADC_GetValue(&hadc2);//获取adc数值
	return adc;	
}
uint16_t getADC1_PB12_VL2(void)//PB12--ADC1_IN11
{
	uint16_t adc = 0;
	HAL_ADC_Start(&hadc1);
	adc = HAL_ADC_GetValue(&hadc1);
	return adc;
}

显示电压函数:

unsigned char buf[20];//存储电压值
sprintf(buf, "      VAL:%.2fV", getADC2_PB15_VL1()*3.3/4096);//转化成电压值,保存在char型变量buf【20】中
LCD_DisplayStringLine(Line8, (uint8_t *)buf);//将cahr型变量转化成unsigned char 型变量,并在lcd中显示
sprintf(buf, "      VAL:%.2fV", getADC1_PB12_VL2()*3.3/4096);	LCD_DisplayStringLine(Line9, (uint8_t *)buf);

解决LCD与LED引脚冲突

先将锁存器LE引脚初始化为低电平,锁存LED状态,需要操作LED时再开启,操作完即关闭,避免LED与LCD的互相影响

image-20241207153800382

TIME1定时1s

选择定时器时钟输入源:

Internal Clock:内部时钟

image-20241207230619582

NVIC开启定时器1更新中断

image-20241207230843318

定时周期1s,(8000PSCX1000ARR)/8*10^6=0.1s

image-20241207230957973

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)//定时器回调函数(中断服务函数)处理定时器周期溢出事件
{
		t++;//定时溢出时执行程序
}
main(){
HAL_TIM_Base_Start_IT(&htim1);//开启定时器中断
......
}

while(1)中

		sprintf(buf, "      t=%d", t);//,保存在char型变量buf【20】中

		LCD_DisplayStringLine(Line8, (uint8_t *)buf);//将cahr型变量转化成unsigned char 型变量,并在lcd中显示

基础定时器TIM6

activate:激活

pluse:脉冲

image-20241207163221162

系统时钟80MHz

image-20241207165548336

定时周期T=(8000X1000)/8X10^6=0.1s

PSC:8000-1,ARR=1000-1

自动重装预寄存器:auto-reload preload,无影响

image-20241208100333267

开启更新中断

image-20241208101041133

频率测量,(定时器输入捕获,当计数器)

image-20241208102212215

R39__PB4 TIM3_CH1,TIM16_CH1

R40__PA15 TIM2_CH1,TIM8_CH1

配置定时器为输入捕获模式

image-20241208204626346

配置PSC为80-1,重装值为0xFFFF(65536)

image-20241208204701583

开启定时器中断

image-20241208204817600

f(捕获)=1MHz(分频后)/计数值

定时器回调函数:

uint32_t  cc1_value_1,cc1_value_2 = 0; uint32_t  f39,f40 = 0;
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)//定时器回调函数
{
	if(htim->Instance ==TIM3)//判断是否是定时器3触发的中断
	{
		cc1_value_1 = __HAL_TIM_GET_COUNTER(&htim3);//获取计数值
		__HAL_TIM_SetCounter(&htim3,0);//清除计数值
		f39 = 1000000/cc1_value_1;//计算频率
		HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_1);//重新启动定时器的输入捕获功能,并使能相应的中断。
	}
		
	if(htim->Instance ==TIM2)
	{
		cc1_value_2 = __HAL_TIM_GET_COUNTER(&htim2);
		__HAL_TIM_SetCounter(&htim2,0);
		f40 = 1000000/cc1_value_2;
		HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);
	}

}

相关初始化

HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);//启动定时器的输入捕获功能,并使能相应的中断。
HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_1);

读取频率

	 while (1)
  {
    /* USER CODE END WHILE */
         
    /* USER CODE BEGIN 3 */
   		sprintf(buf, "  FRQ(R39):%dHz   ",f39);
		LCD_DisplayStringLine(Line8, (uint8_t *)buf);
		HAL_Delay(200);
			
		sprintf(buf, "  FRQ(R40):%dHz   ",f40);
		LCD_DisplayStringLine(Line9, (uint8_t *)buf);
		HAL_Delay(200);
  }

PWM输出(占空比调节)

PA2__TIM2_CH2

选择定时器2通道2功能为

image-20241210151706138

设置为1Khz频率

PSC:800

ARR:100

f输出=80MHz/(PSC*ARR)=80x10^6/(800x100)=1000hz

image-20241210152445386

开启输出比较

image-20241210152757813

不用设置定时器中断(不开启)

初始化PWM输出

HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2);//开启time2,通道2pwm输出
TIM2->CCR2 =50;
uint16_t pwmduty=50;//占空比

占空比=输出比较寄存器值/自动重装载值,pwmduty=CCR/ARR=CCR2/100,即在ARR=100时,CCR的值即为占空比(<=100)

更改占空比(自己定义)

	TIM2->CCR2 =pwmduty;
	pwmduty++;
	HAL_Delay(10);
	if(pwmduty>95)pwmduty=0;

EEPROM(移植库文件,无需CubeMX配置)

image-20241210160110510

A2=A1=A0=0

地址0xa0写

0xa1读

将下面文件拷贝进工程

image-20241210165141995

引用头文件

在i2c_hal.c文件中编写iic读取EEPROM和写入函数

写入函数(器件内地址,要写入的数据)

void eeprom_write(uint8_t addr, uint8_t dat)
{
	I2CStart();
	I2CSendByte(0xa0);//器件地址
	I2CWaitAck();//等待应答
	I2CSendByte(addr);//期间内要操作的地址0~255???
	I2CWaitAck();
	I2CSendByte(dat);//写入的数据
	I2CWaitAck();
	I2CStop();
	

	HAL_Delay(20);

}

读取函数(器件内地址)

uint8_t eeprom_read(uint8_t addr)
{
	I2CStart();
	I2CSendByte(0xa0);//器件地址
	I2CWaitAck();//等待应答
	I2CSendByte(addr);//期间内要操作的地址0~255???
	I2CWaitAck();
	I2CStop();	
	
	I2CStart();
	I2CSendByte(0xa1);//读取命令
	I2CWaitAck();
	uint8_t dat = I2CReceiveByte();//接收数据
	I2CSendNotAck();   //主机不应答 从机不再发数据
	I2CStop();	
	
	return dat;

}

初始化,写入,读取

I2CInit();
eeprom_write(0, 15);//在0地址写入15

uint8_t dat = eeprom_read(0);//读取0地址
char text[20];

显示到Lcd

	sprintf(text, "      %d       ", dat);//将数据dat转化成字符串保存在text数组变量中
	LCD_DisplayStringLine(Line0, (uint8_t *)text);
posted @   沁拒离  阅读(90)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 【.NET】调用本地 Deepseek 模型
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
点击右上角即可分享
微信分享提示