当前位置:   article > 正文

蓝桥杯嵌入式速成

蓝桥杯嵌入式速成

cubmx创建工程

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

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

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

利用官方提供的LCD代码创建工程(15届不能用)

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

利用官方提供的LCD代码创建工程(15届能用)

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

在这里插入图片描述

在这里插入图片描述

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

Keil配置

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

头文件注意

在这里插入图片描述

使用sprintf需要加头文件stdio.h
使用memset需要加头文件string.h

其他注意

如果要在main使用需要extern
uwTick 1ms加一次

Led 需要用LedDisp(0)初始化
串口接收初始化HAL_UART_Receive_IT(&huart1,&rx_data,1);
串口不工作看中断是不是打开,引脚是不是PA9,PA10
PWM初始化HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_4);
输入捕获初始化HAL_TIM_IC_Start_IT(&htim16, TIM_CHANNEL_1);;
I2C 需要用I2CInit()初始化
EEP开始需要第一次先写入题目要求的合法数据 之后再读
EEP 写0xa0 读(先写要读的地址) 0xa1
mcp 写0x5e0x5f

在这里插入图片描述

LED

在这里插入图片描述
Led初始化LedDisp(0)


void LED_disp(u8 led)
{
	HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET); //打开锁存器
	HAL_GPIO_WritePin(GPIOC,0xFF00,GPIO_PIN_SET);	// set熄灭
	HAL_GPIO_WritePin(GPIOC,led<<8,GPIO_PIN_RESET);	// reset点亮
	HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET); //关闭锁存器
}



vu32 ledTick = 0;
u8 led = 0;
void LED_proc()
{
	if(uwTick - ledTick  < 100) return;	
	ledTick = uwTick;
	
	LED_disp(led);
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

闪烁

在这里插入图片描述

按键

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

u8 ko,kv,ku,kd = 0;

void KeyRead()
{
  //5行四个按键
  if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0) == 0) kv = 1;
  else if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1) == 0) kv = 2;
  else if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2) == 0) kv = 3;
  else if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == 0) kv = 4;
  else kv = 0;// 默认给值为0,这里别忘记了
  
  kd = kv &(ko ^ kv);
  ku = ~kv &(ko ^ kv);
  ko = kv;  
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

短按

vu32 keyTick = 0;
void KeyProc()
{
  if(uwTick - keyTick < 20) return;
  keyTick =uwTick;
  
  KeyRead();
  if(kd == 1)
  {
  }
  else if(kd == 2)
  {
  }
  else if(kd == 3)
  {
  }
  else if(kd == 4)
  {
  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

长按

vu32 keyTick = 0;
vu32 keyLongTick = 0;
void KeyProc()
{
  if(uwTick - keyTick < 20) return;
  keyTick = uwTick;
  
  KeyRead();
  
  if(ku == 1) //注意用ku
  {
	//短按
  }
  else if(ku == 2 && (uwTick - keyLongTick < 800)) 
  {
  	//短按
	//注意要防止长按抬手触发短按多加了一个判断条件
  }
  else if(ku == 3 && (uwTick - keyLongTick < 800))
  {
  } 
  else if(ku == 4 && (uwTick - keyLongTick < 800))
  {
  }
  else if(kd == 2 || kd == 3 || kd == 4)
  {
  	//开始长按计时
    keyLongTick = uwTick;
  }
  
  if(kv == 2 && (uwTick - keyLongTick > 800))
  {
    //长按操作
  }
  
  if(kv == 3 && (uwTick - keyLongTick > 800))
  {
	//长按操作
  }
  
  if(kv == 4 && (uwTick - keyLongTick > 800))
  {
    //长按操作
  }
  
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46

双击


u8 keyStatus;
u32 keyTick;
u32 keyIdle = 0;
u32 doubleTick = 0;
void Key_proc()
{
	if(uwTick - key_tick < 20) return;
	key_tick = uwTick;

	KEY_read();
	
	keyIdle = uwTick - doubleTick ;//2次按键间隔的时间,单位ms
	//之前没有按下
	if(kd ==  1 && keyStatus == 0)
	{
		keyStatus = 1;
		doubleTick = uwTick;		//按下变为状态1,开始计时
	}
	else if(keyStatus  == 1)
	{
	//如果400ms内再按触发双击,如果第一次按后400ms没按则才触发单击,这里改为300ms也可以,我感觉有点快
		if(keyIdle < 400 && kd == 1)	
		{
			//双击操作
			keyStatus = 0;
		}
		else if(key_idle > 400)
		{
			//单击
			keyStatus= 0;
		}
	}
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

LCD

LCD最多21位

高亮行

if(pwm_line == 0)
	LCD_SetBackColor(Green);
sprintf((char *)lcd_buf,"   PA3_F:%-5dHz     ",pa3_frq);	
LCD_DisplayStringLine(Line2,lcd_buf);
LCD_SetBackColor(Black);
		
if(pwm_line == 1)
	LCD_SetBackColor(Green);
sprintf((char *)lcd_buf,"   PA3_D:%d %%        ",pa3_duty);	
LCD_DisplayStringLine(Line3,lcd_buf);
LCD_SetBackColor(Black);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

高亮字符

if(b2wz == 1 ) LCD_SetBackColor(Red);
LCD_DisplayChar(Line4,320-(4 * 16),times[ccwz].h/10+'0');
LCD_DisplayChar(Line4,320-(5 * 16),times[ccwz].h%10+'0');
LCD_SetBackColor(Blue);

LCD_DisplayChar(Line4,320-(6 * 16),':');

 if(b2wz == 2) LCD_SetBackColor(Red);
 LCD_DisplayChar(Line4,320-(8 * 16),times[ccwz].m/10+'0');
 LCD_DisplayChar(Line4,320-(9 * 16),times[ccwz].m%10+'0');
 LCD_SetBackColor(Blue);
 
LCD_DisplayChar(Line4,320-(10 * 16),':');

if(b2wz == 3) LCD_SetBackColor(Red);
LCD_DisplayChar(Line4,320-(12 * 16),times[ccwz].s/10+'0');
LCD_DisplayChar(Line4,320-(13 * 16),times[ccwz].s%10+'0');
LCD_SetBackColor(Blue);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

RTC

可以找例程在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

RTC_DateTypeDef D;
RTC_TimeTypeDef T;
u32 rtc_tick = 0;
void RTC_proc()
{
	if(uwTick - rtc_tick < 100)
		rtc_tick = uwTick;
  /* Get the RTC current Time */
  HAL_RTC_GetTime(&hrtc, &T, RTC_FORMAT_BIN);
  /* Get the RTC current Date */
  HAL_RTC_GetDate(&hrtc, &D, RTC_FORMAT_BIN);
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

ADC

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

如果双通道需要配置
在这里插入图片描述
采样时间选最大
在这里插入图片描述

u32 r37_value = 0;
u32 r38_value = 0;
u32 mcp_value = 0;
float r37_volt = 0;
float r38_volt = 0;
float mcp_volt = 0;
u32 adc_tick = 0;
void ADC_proc()
{
	if(uwTick - adc_tick < 100)
		return;
	adc_tick = uwTick;
	//就这两个函数
	HAL_ADC_Start(&hadc1);
	mcp_value = HAL_ADC_GetValue(&hadc1);
	
	HAL_ADC_Start(&hadc1);
	r38_value = HAL_ADC_GetValue(&hadc1);
	
	HAL_ADC_Start(&hadc2);
	r37_value = HAL_ADC_GetValue(&hadc2);
	
	r37_volt = r37_value * 3.3 / 4096.0;
	r38_volt = r38_value * 3.3 / 4096.0;
	mcp_volt = mcp_value * 3.3 / 4096.0;	

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

I2C

I2C 需要用I2CInit初始化

//写9行
void EEpWrite(uint8_t addr,uint8_t data)
{
  I2CStart();
  I2CSendByte(0xa0);
  I2CWaitAck();
  I2CSendByte(addr);
  I2CWaitAck();
  I2CSendByte(data);
  I2CWaitAck();
  I2CStop();
  HAL_Delay(5);
}
//读13行
uint8_t EEpRead(uint8_t add)
{
	uint8_t data;
	I2CStart();
	I2CSendByte(0xa0);
	I2CWaitAck();
	I2CSendByte(add);
	I2CWaitAck();
	
	I2CStart();
	I2CSendByte(0xa1);
	I2CWaitAck();
	data = I2CReceiveByte();
	I2CSendNotAck(); //注意是noack
	I2CStop();
	return data;
}


void MCP_write(uint8_t mcp)
{
	I2CStart();
	I2CSendByte(0x5E);
	I2CWaitAck();
	I2CSendByte(mcp);
	I2CWaitAck();
	I2CStop();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

uart

在这里插入图片描述

接收

串口接收初始化HAL_UART_Receive_IT(&huart1,&rx_data,1);
接收中断3行

u8 rx_pointer , rx_data;
u8 rx_buff[30];
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	rx_tick = uwTick;
	HAL_UART_Receive_IT(&huart1,&rx_data,1);
	rx_buff[rx_pointer++] = rx_data;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

接收处理

u32 rx_tick = 0;
void RX_proc()
{
	if(uwTick - rx_tick < 50) return;
	rx_tick = uwTick;
	if(rx_pointer == 1 && rx_buff[0] == '#')
	{
		//接收输出正确
	}
	else if(rx_pointer > 0)
	{
		//接收输出错误
	}
	rx_pointer = 0;
	memset(rx_buff,0,sizeof(rx_buff));
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

发送

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

#include <stdio.h>
struct __FILE
{
  int handle;
  /* Whatever you require here. If the only file you are using is */
  /* standard output using printf() for debugging, no file handling */
  /* is required. */
};
/* FILE is typedef’d in stdio.h. */
FILE __stdout;
int fputc(int ch, FILE *f) 
{
	HAL_UART_Transmit(&huart1,(u8 *)&ch,1,50);
  /* Your implementation of fputc(). */
  return ch;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

然后就可以通过printf发送串口数据

PWM

不要用同一个定时器设置不同引脚的PWM
PWM初始化HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_4);在这里插入图片描述 在这里插入图片描述

u16 pa3_frq = 1000;
u16 pa4_frq = 2000;
u8 pa3_duty = 50;
u8 pa4_duty = 50;
u32 pwm_tick = 0;
void PWM_proc()
{
	if(uwTick - pwm_tick < 100)return;
	pwm_tick = uwTick; 
	
	__HAL_TIM_SetAutoreload(&htim2,1e6 / pa3_frq - 1);
	__HAL_TIM_SetCompare(&htim2,TIM_CHANNEL_4,(1e6 / pa3_frq) * pa3_duty / 100);
	
	__HAL_TIM_SetAutoreload(&htim3,1e6 / pa4_frq - 1);
	__HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_2,1e6 / pa4_frq * pa4_duty / 100);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

DAC

在这里插入图片描述

u16 dac_value = 0;
u32 dac_tick = 0;
void DAC_proc()
{
	if(uwTick - dac_tick < 100) return;
	dac_tick = uwTick;
	HAL_DAC_SetValue(&hdac1,DAC_CHANNEL_2,DAC_ALIGN_12B_R,dac_value);
	HAL_DAC_Start(&hdac1,DAC_CHANNEL_2);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

定时器

定时器先配置定时时间 然后打开中断 然后打开定时器 即可
在这里插入图片描述

捕获PWM频率+占空比

PA15 -> R39
PA4 -> R40
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
打开列程
在这里插入图片描述
打开输出捕获中断
在这里插入图片描述
我们改成我们需要的
在这里插入图片描述
回调函数也复制过去
在这里插入图片描述
变量也复制过去
在这里插入图片描述
我们有俩个定时器所以要先判断一下
在这里插入图片描述

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

占空比

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/405337
推荐阅读
相关标签
  

闽ICP备14008679号