蓝桥杯嵌入式基于STM32G4的模块总结【HAL库】【省赛】

文章目录

  • 前言
    • 硬件资源
    • 下载方式
  • 模块总结
    • 时钟树
    • LED灯
    • 键盘
    • LCD
    • USART串口
    • EEPROM
    • MCP4017可编程电阻
    • ADC
    • DAC
    • 测量PWM频率和占空比
    • 定时器生成PWM波
    • RTC时钟
  • 写在最后


前言

由于去年大一的时候学了会单片机。参加了蓝桥杯单片机组,虽然只获得了一个省奖,但是带领我进入了单片机的世界,今年参加嵌入式组,由于之前一段时间去学CV去了,所以现在趁着这个机会复习一下stm32

硬件资源

嵌入式竞赛实训平台(CT117E-M4) 是北京国信长天科技有限公司设计、生产的一款“蓝桥杯全国软件与信息技术专业人才大赛-嵌入式设计与开发科目”专用竞赛平台,平台以STM32G431RBT6为主控芯片,预留扩展板接口,可为用户提供丰富的实验场景。蓝桥杯嵌入式基于STM32G4的模块总结【HAL库】【省赛】_第1张图片蓝桥杯嵌入式基于STM32G4的模块总结【HAL库】【省赛】_第2张图片蓝桥杯嵌入式基于STM32G4的模块总结【HAL库】【省赛】_第3张图片

下载方式

蓝桥杯嵌入式基于STM32G4的模块总结【HAL库】【省赛】_第4张图片
由于板载了DAP Link,所以直接接入CN2(USB-Type)接口,并保证NRST、SWCLK、SWDIO的跳线连接,即可下载程序
CT117E-M4还板载了USB转串口功能默认与STM32G431RBT6的USART1连接。

模块总结

时钟树

蓝桥杯嵌入式基于STM32G4的模块总结【HAL库】【省赛】_第5张图片
选择24M外部高速晶振

  • CubeMx配置
    蓝桥杯嵌入式基于STM32G4的模块总结【HAL库】【省赛】_第6张图片

蓝桥杯嵌入式基于STM32G4的模块总结【HAL库】【省赛】_第7张图片

LED灯

蓝桥杯嵌入式基于STM32G4的模块总结【HAL库】【省赛】_第8张图片

  • CubeMx配置
    蓝桥杯嵌入式基于STM32G4的模块总结【HAL库】【省赛】_第9张图片

PC8-PC15:

  • GPIO output lebel:High
  • GPIO mde:Output Push Pull
  • GPIO Pull:No pull-up and no pull-down

PD2:

  • GPIO output lebel:Low
  • GPIO mde:Output Push Pull
  • GPIO Pull:No pull-up and no pull-down
void LED_Disp(unsigned char Led)
{
	//**将所有的灯熄灭
	HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_8
												|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12, GPIO_PIN_SET);
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);		
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);

	//根据ucLed的数值点亮相应的灯
	//LD8-LD1对应Led的8个位
	HAL_GPIO_WritePin(GPIOC, Led<<8, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);		
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);	
}

蓝桥杯嵌入式基于STM32G4的模块总结【HAL库】【省赛】_第10张图片

  • 我们可以在hal_gpio.h里找到所有hal库关于gpio的函数,其他的功能的函数都可以在对应的.h文件里找到

键盘

蓝桥杯嵌入式基于STM32G4的模块总结【HAL库】【省赛】_第11张图片

  • CubeMx配置
    蓝桥杯嵌入式基于STM32G4的模块总结【HAL库】【省赛】_第12张图片
  • GPIO mde:Input mode
  • GPIO Pull:No pull-up and no pull-down
unsigned char Key_Scan(void)
{
	unsigned char unKey_Val = 0;
	
	if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0) == GPIO_PIN_RESET)unKey_Val = 1;
	if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) == GPIO_PIN_RESET)unKey_Val = 2;
	if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2) == GPIO_PIN_RESET)unKey_Val = 3;
	if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET)unKey_Val = 4;	
	
	return unKey_Val;
}
void Key_Proc(void)
{
	//利用嘀嗒定时器消抖减速
	if((uwTick -  uwTick_Key)<100)	return;
	uwTick_Key = uwTick;	
	
	ucKey_Val = Key_Scan();
	unKey_Down = ucKey_Val & (ucKey_Old ^ ucKey_Val); 
	ucKey_Up = ~ucKey_Val & (ucKey_Old ^ ucKey_Val);	
	ucKey_Old = ucKey_Val;
	switch(unKey_Down)
	{
		case 1:
		...
	}
}

LCD

  • 比赛的时候官方会给我们提供驱动程序,所以我们只需移植就行了

蓝桥杯嵌入式基于STM32G4的模块总结【HAL库】【省赛】_第13张图片
蓝桥杯嵌入式基于STM32G4的模块总结【HAL库】【省赛】_第14张图片
蓝桥杯嵌入式基于STM32G4的模块总结【HAL库】【省赛】_第15张图片
蓝桥杯嵌入式基于STM32G4的模块总结【HAL库】【省赛】_第16张图片

  • 我们在需要在自己的BSP的文件夹里移植这3个文件就可以了
    -蓝桥杯嵌入式基于STM32G4的模块总结【HAL库】【省赛】_第17张图片
  • 别忘了在MDK里添加文件路径
void LCD_Init(void);
void LCD_SetTextColor(vu16 Color);
void LCD_SetBackColor(vu16 Color);
void LCD_ClearLine(u8 Line);
void LCD_Clear(u16 Color);
void LCD_SetCursor(u8 Xpos, u16 Ypos);
void LCD_DrawChar(u8 Xpos, u16 Ypos, uc16 *c);
void LCD_DisplayChar(u8 Line, u16 Column, u8 Ascii);
void LCD_DisplayStringLine(u8 Line, u8 *ptr);
void LCD_SetDisplayWindow(u8 Xpos, u16 Ypos, u8 Height, u16 Width);
void LCD_WindowModeDisable(void);
void LCD_DrawLine(u8 Xpos, u16 Ypos, u16 Length, u8 Direction);
void LCD_DrawRect(u8 Xpos, u16 Ypos, u8 Height, u16 Width);
void LCD_DrawCircle(u8 Xpos, u16 Ypos, u16 Radius);
void LCD_DrawMonoPict(uc32 *Pict);
void LCD_WriteBMP(u32 BmpAddress);
void LCD_DrawBMP(u32 BmpAddress);
void LCD_DrawPicture(const u8* picture);

/*----- Medium layer function -----*/
void LCD_WriteReg(u8 LCD_Reg, u16 LCD_RegValue);
u16 LCD_ReadReg(u8 LCD_Reg);
void LCD_WriteRAM_Prepare(void);
void LCD_WriteRAM(u16 RGB_Code);
u16 LCD_ReadRAM(void);
void LCD_PowerOn(void);
void LCD_DisplayOn(void);
void LCD_DisplayOff(void);

/*----- Low layer function -----*/
void LCD_CtrlLinesConfig(void);

void LCD_BusIn(void);
void LCD_BusOut(void);
  • 就可以直接调用LCD的API了
LCD_Init(); //常用的一些函数
LCD_Clear(White);
LCD_SetBackColor(White);
LCD_SetTextColor(Blue);	
sprintf((char *)Lcd_Disp_String, "   Hello world!!!");
LCD_DisplayStringLine(Line1, Lcd_Disp_String);

蓝桥杯嵌入式基于STM32G4的模块总结【HAL库】【省赛】_第18张图片

USART串口

蓝桥杯嵌入式基于STM32G4的模块总结【HAL库】【省赛】_第19张图片

  • 由于板载了USB-串口,所以我们接上USB线就能用USART1

  • CubeMx配置蓝桥杯嵌入式基于STM32G4的模块总结【HAL库】【省赛】_第20张图片蓝桥杯嵌入式基于STM32G4的模块总结【HAL库】【省赛】_第21张图片
    在这里插入图片描述

  • GPIO记得选择PA9 PA10

  • 波特率可自行选择,和串口助手相同就行

  • 开启中断

//发送
HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)
  • UART_HandleTypeDef *huart UATR的别名 如 : UART_HandleTypeDef huart1; 别名就是huart1
  • *pData 需要发送的数据
  • Size 发送的字节数
  • Timeout 最大发送时间,发送数据超过该时间退出发送
//接受
HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
  • UART_HandleTypeDef *huart UATR的别名 如 : UART_HandleTypeDef huart1; 别名就是huart1
  • *pData 接收到的数据存放地址
  • Size 接收的字节数
//常用格式
//串口中断开启
HAL_UART_Receive_IT(&huart1, &rx_buffer, 1);
//串口中断回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	LED(ON);
	HAL_UART_Receive_IT(&huart1, &rx_buffer, 1);//这一句一定要加
}
//重定向c库函数printf
int fputc(int ch, FILE *f)
{
  HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);
  return ch;
}
//重定向c库函数getchar,scanf
int fgetc(FILE *f)
{
  uint8_t ch = 0;
  HAL_UART_Receive(&huart1, &ch, 1, 0xffff);
  return ch;
}

EEPROM

蓝桥杯嵌入式基于STM32G4的模块总结【HAL库】【省赛】_第22张图片
蓝桥杯嵌入式基于STM32G4的模块总结【HAL库】【省赛】_第23张图片

蓝桥杯嵌入式基于STM32G4的模块总结【HAL库】【省赛】_第24张图片

  • M24C02通过IIC通信接在单片机的PB6 PB7上,我们直接移植官方的代码
//EEPROM读写代码
void eeprom_write(unsigned char *pucBuf, unsigned char ucAddr, unsigned char Size)
{
	I2CStart();
	I2CSendByte(0xa0);
	I2CWaitAck();
	
	I2CSendByte(ucAddr);	
	I2CWaitAck();
	
	while(Size--)
	{
		I2CSendByte(*pucBuf++);
		I2CWaitAck();	
	}
	I2CStop();
	delay1(500);	
}

void eeprom_read(unsigned char *pucBuf, unsigned char ucAddr, unsigned char Size)
{
	I2CStart();
	I2CSendByte(0xa0);
	I2CWaitAck();
	
	I2CSendByte(ucAddr);	
	I2CWaitAck();
	
	I2CStart();
	I2CSendByte(0xa1);
	I2CWaitAck();
	
	while(ucNum--)
	{
		*pucBuf++ = I2CReceiveByte();
		if(Size)
			I2CSendAck();	
		else
			I2CSendNotAck();
	}
	I2CStop();	
}

MCP4017可编程电阻

蓝桥杯嵌入式基于STM32G4的模块总结【HAL库】【省赛】_第25张图片
蓝桥杯嵌入式基于STM32G4的模块总结【HAL库】【省赛】_第26张图片
蓝桥杯嵌入式基于STM32G4的模块总结【HAL库】【省赛】_第27张图片

  • 这就是MC94017的内部结构,总的来说就是接通开关,电阻分压
  • 下面是计算公式
    在这里插入图片描述
  • MCP4017地址
    蓝桥杯嵌入式基于STM32G4的模块总结【HAL库】【省赛】_第28张图片
void resistor_write(uint8_t value)
{
	I2CStart();
	I2CSendByte(0x5E);
	I2CWaitAck();
	
	I2CSendByte(value);
	I2CWaitAck();	
	I2CStop();	
}

uint8_t resistor_read(void)
{
	uint8_t value;
	I2CStart();
	I2CSendByte(0x5F);
	I2CWaitAck();
	
	value = I2CReceiveByte();
	I2CSendNotAck();	
	I2CStop();	
	
	return value;
}

ADC

  • 由于STM32的ADC的配置方式有很多种,这里我们只介绍常见的几种
  • CubeMx配置介绍
    蓝桥杯嵌入式基于STM32G4的模块总结【HAL库】【省赛】_第29张图片
  • 单次转换模式:ADC只执行一次转换
  • 连续转换模式:转换结束之后马上开始新的转换
  • 扫描模式:ADC扫描被规则通道和注入通道选中的所有通道,在每个组的每个通道上执行单次转换。
  • 间断模式:触发一次,转换一个通道,在触发,在转换。在所选转换通道循环,由触发信号启动新一轮的转换,直到转换完成为止。

单ADC采集:
蓝桥杯嵌入式基于STM32G4的模块总结【HAL库】【省赛】_第30张图片蓝桥杯嵌入式基于STM32G4的模块总结【HAL库】【省赛】_第31张图片

  • 这里我们通过R38来调节PB12通道采集到的电压
  • CubeMx配置
    在这里插入图片描述在这里插入图片描述在这里插入图片描述
    蓝桥杯嵌入式基于STM32G4的模块总结【HAL库】【省赛】_第32张图片蓝桥杯嵌入式基于STM32G4的模块总结【HAL库】【省赛】_第33张图片
  • 注意时钟选择,其他的可自行选择设置
uint16_t getADC1(void)
{
	uint16_t adc_value = 0;
	
	HAL_ADC_Start(&hadc1);
	adc_value = HAL_ADC_GetValue(&hadc1);
	
	return adc_value;
}

多ADC采集:
蓝桥杯嵌入式基于STM32G4的模块总结【HAL库】【省赛】_第34张图片蓝桥杯嵌入式基于STM32G4的模块总结【HAL库】【省赛】_第35张图片

  • 这里我们选择R37调节PB15
    在这里插入图片描述在这里插入图片描述
  • 和上面ADC1一样的配置即可
//只需把hadc1改为hadc2
uint16_t getADC2(void)
{
	uint16_t adc_value = 0;
	
	HAL_ADC_Start(&hadc2);
	adc_value = HAL_ADC_GetValue(&hadc2);
	
	return adc;
}
  • 这只是最基础的ADC使用
  • 如果有需要还可以开启中断
  • 单ADC多通道可以开启DMA模式

DAC

  • CubeMx配置
    蓝桥杯嵌入式基于STM32G4的模块总结【HAL库】【省赛】_第36张图片在这里插入图片描述蓝桥杯嵌入式基于STM32G4的模块总结【HAL库】【省赛】_第37张图片
  • DAC功能很多。但是比赛赛题里很少出现,这里不过多赘述
void DAC_OUT(float Val)
{
	uint32_t temp;
	temp = (Val*4096/3.3f);
	HAL_DAC_SetValue(&hdac1, DAC_CHANNEL_1, DAC_ALIGN_12B_R, temp);
}

测量PWM频率和占空比

蓝桥杯嵌入式基于STM32G4的模块总结【HAL库】【省赛】_第38张图片

  • 我们用板载的XL555信号发生器来生成PWM波,采集引脚为PA15
  • CubeMx配置
    在这里插入图片描述
    蓝桥杯嵌入式基于STM32G4的模块总结【HAL库】【省赛】_第39张图片
  • 复位Reset模式:使用内部时钟作为时钟源,TI1/2外部有效信号复位计数器。例如,CH1触发输入上升沿有效时,计数器复位到默认值0。

原理:蓝桥杯嵌入式基于STM32G4的模块总结【HAL库】【省赛】_第40张图片
1.选择通道一测量pwm的频率和占空比,上升沿触发
2.当上升沿来临时,②中寄存器会存下计数值,会触发中断,然后清零,这个值记做T
3.当下降沿来临时,③中寄存器会存下计数值,会触发中断,不会清零,这个值记做D
蓝桥杯嵌入式基于STM32G4的模块总结【HAL库】【省赛】_第41张图片

  • 我们设置的80分频,所以只有1M的频率
  • 频率 = 1000000 / T
  • 占空比 = D / T
  • 我们在中断中读这两个寄存器的值,就可以计算出频率和占空比了
  • 这样在看CubeMx的配置就清晰很多了
    蓝桥杯嵌入式基于STM32G4的模块总结【HAL库】【省赛】_第42张图片在这里插入图片描述
/* 启动定时器 */
HAL_TIM_Base_Start(&htim2);
/* 启动定时器通道输入捕获并开启中断 */
HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_1);		
HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_2);	
//输入捕获中断回调函数
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
	
	  if(htim->Instance==TIM2)
 	 {
		if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
		{
			T_Count =  HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_1)+1;
			Freq = 1000000 / T_Count;
			Duty = (float)D_Count/T_Count * 100;
		}
		else if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
		{
			D_Count =  HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_2)+1;
		}			
			
	}	
}

定时器生成PWM波

蓝桥杯嵌入式基于STM32G4的模块总结【HAL库】【省赛】_第43张图片

  • 我们利用PA2来实现PWM输出
  • CubeMx配置
    蓝桥杯嵌入式基于STM32G4的模块总结【HAL库】【省赛】_第44张图片蓝桥杯嵌入式基于STM32G4的模块总结【HAL库】【省赛】_第45张图片

PWM频率:
Fpwm =Tclk / ((arr+1)*(psc+1))(单位:Hz)

  • arr 是计数器值
  • psc 是预分频值

占空比:
duty circle = TIM15->CCR1 / arr(单位:%)

  • TIM15->CCR1 用户设定值
  HAL_TIM_PWM_Start(&htim15,TIM_CHANNEL_1);

RTC时钟

  • CubeMx配置
    蓝桥杯嵌入式基于STM32G4的模块总结【HAL库】【省赛】_第46张图片
//RTC相关变量
RTC_TimeTypeDef H_M_S_Time;
RTC_DateTypeDef Y_M_D_Date;
uint8_t Second;

//函数调用
HAL_RTC_GetTime(&hrtc, &H_M_S_Time, RTC_FORMAT_BIN);//读取日期和时间必须同时使用
HAL_RTC_GetDate(&hrtc, &Y_M_D_Date, RTC_FORMAT_BIN);

写在最后

离比赛时间不远了,接下来就是做几套真题,希望大家和我都能取得一个好成绩,加油加油加油
对了,总结几个我写程序平常容易出错的地方:

  • 记得配置中断优先级
  • 串口波特率双方一定要相同
  • 出BUG了一定不要着急,从配置开始检查,在检查代码
    蓝桥杯嵌入式基于STM32G4的模块总结【HAL库】【省赛】_第47张图片
    大家冲冲冲

你可能感兴趣的:(蓝桥杯嵌入式,stm32,蓝桥杯)