蓝桥杯嵌入式省赛考点模块最简书写方式详解

一、key和led

使用结构体,让定时器10ms扫一次按键

struct key{
		uint8_t key_next;
		uint8_t key_flag;
		uint8_t key_up;
		uint8_t key_long_flag;
		uint8_t key_time;
};
struct key keys[4]={0,0,0};
if(htim->Instance==TIM2)
	{
			keys[0].flag= HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0);//b1
			keys[1].flag= HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1);//b2
			keys[2].flag= HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2);//b3
			keys[3].flag= HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0);//b4
			for(i=0;i<4;i++)
				switch(keys[i].next){
					case 0 : if(keys[i].flag==0){	
								keys[i].next=1;
								keys[i].timer=0;
						}break;
					case 1 : if(keys[i].flag==0){	
								keys[i].next=2;
						}else{
								keys[i].next=0;
						}break;
					case 2 : if(keys[i].flag==1){	
								keys[i].next=0;
								if(keys[i].timer<70){
									keys[i].short_flag=1;
								}
						}else{
							keys[i].timer++;
							if(keys[i].timer>70){
								keys[i].long_flag=1;
							}
						}break;
				}
	}

led显示

void LED_Disp(unsigned char dsLED)
{
	HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);//开锁存器
	HAL_GPIO_WritePin(GPIOC,GPIO_PIN_All,GPIO_PIN_SET);//所有LED熄灭(l小写)
	HAL_GPIO_WritePin(GPIOC,dsLED<<8,GPIO_PIN_RESET);//左移8位:控制C8-15引脚,值为1的点亮
	HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);//关锁存器
}

//打开对应led
led_1|=0x01;
LED_Disp(led_1);
//流水灯高4位
led_1 &= 0x0f;
led_1 |= (1<<LED_flow_up);
LED_flow_up ++ ;
if(LED_flow_up == 8)
LED_flow_up = 4;

二、uart

串口重定向(包含stdio.h,魔法棒勾选)

int fputc(int ch,FILE *f){
	HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 1000);
	return ch;
}

串口接收(main.c函数打开接收中断) memset函数包含头文件string.h

使用这个函数HAL_UART_Receive_IT(&huart1,&aRxBuffer,1);

uint8_t aRxBuffer;			//接收中断缓冲
uint8_t Uart1_RxBuff[10] = {0};		//接收缓冲
uint8_t Uart1_Rx_Cnt = 0;		//接收缓冲计数
//回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  	UNUSED(huart);
	Uart1_RxBuff[Uart1_Rx_Cnt++] = aRxBuffer;   //接收数据转存
	HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBuffer, 1);   //再开启接收中断
}
//用户实现中断调用或者main函数调用
void uart(void){
	if(Uart1_Rx_Cnt==7){
		if(('0'<=Uart1_RxBuff[0]&&Uart1_RxBuff[0]<='9')&&('0'<=Uart1_RxBuff[1]&&Uart1_RxBuff[1]<='9')
			&&('0'<=Uart1_RxBuff[2]&&Uart1_RxBuff[2]<='9')&&(Uart1_RxBuff[3]=='-')&&
		('0'<=Uart1_RxBuff[4]&&Uart1_RxBuff[4]<='9')&&('0'<=Uart1_RxBuff[5]&&Uart1_RxBuff[5]<='9')
		&&('0'<=Uart1_RxBuff[6]&&Uart1_RxBuff[6]<='9'))
        {
			Uart1_RxBuff[0]-=0x30;//将字符数据转换为整型数据,反之则相加
			Uart1_RxBuff[1]-=0x30;
			Uart1_RxBuff[2]-=0x30;
			if((key_data[0]==Uart1_RxBuff[0]) && (key_data[1]==Uart1_RxBuff[1])
            	&&(key_data[1]==Uart1_RxBuff[1]))
             {
				key_data[0]=Uart1_RxBuff[4]-0x30;
				key_data[1]=Uart1_RxBuff[5]-0x30;
				key_data[2]=Uart1_RxBuff[6]-0x30;
              
				Uart1_Rx_Cnt = 0;
				memset(Uart1_RxBuff,0x00,sizeof(Uart1_RxBuff));//清除内存
			}
		}
	}
}
//得到一个十位数as
data=(Uart1_RxBuff[6]-0x30)*10+Uart1_RxBuff[7]-0x30;

三、tim

使能定时器

 预分频系数设置为 8000-1, fCK_CNT=80MHz/8000=10KHz。 这样就得到计数器的计数频率为 10KHz,即计数器 1 秒钟可以计 10000 个数。

//纯定时器回调函数
__weak void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
  UNUSED(htim);
    /* 用户内容 */
}

/* 
//打开定时器  打开地方用户自定义
HAL_TIM_Base_Start_IT(&htim4);

//关闭定时器

HAL_TIM_Base_Stop_IT(&htim2);	
*/

四、pwm

80Mhz/80=1Mhz 的计数频率,自动重装载为 500,那么 PWM 频率为 1Mhz/500=2kHZ

HZ计算公式:80000000/80/1000hz=1000(计数值)

占空比 上图:500-1

输入分频系数 以及 计数值

//开启输出pwm  开启地方自定义

​HAL_TIM_PWM_Start(&htim5, TIM_CHANNEL_3);

//用户可自定义修改
__HAL_TIM_SET_AUTORELOAD(&htim5,499);//设置自动重装载值
__HAL_TIM_SET_COMPARE(&htim5,TIM_CHANNEL_3,50);//设置占空比

五、捕获输入

十四届省赛考过,说明国赛考点下放也需要学习除了扩展版的所有考点

分频系数为80-1

通道一为上升沿 通道二为下降沿

uint32_t ccr1_val2a=0;
uint32_t ccr1_val2b=0;
uint16_t frq2=0;//频率
uint32_t duty=0;//占空比
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
	if(htim->Instance==TIM3)
	{
		if(htim->Channel==HAL_TIM_ACTIVE_CHANNEL_1)//中断消息来源 选择直接输入的通道
		{
			ccr1_val2a=HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_1);
			ccr1_val2b=HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_2);
			__HAL_TIM_SetCounter(htim,0);
			frq2=(80000000/80)/ccr1_val2a;
	 		duty=(ccr1_val2b*100)/ccr1_val2a;
			HAL_TIM_IC_Start(htim,TIM_CHANNEL_1);
			HAL_TIM_IC_Start(htim,TIM_CHANNEL_2);
		}
	}
}

六、lcd

包含官方库文件(复制以下文件到自己工程中)

 

//main函数调用
LCD_Init();
LCD_Clear(Black);
LCD_SetBackColor(Black);
LCD_SetTextColor(White);
//用户使用
if(set_cnt==2)LCD_SetBackColor(Blue);
		else LCD_SetBackColor(Black);//高亮
//基础显示
LCD_DisplayStringLine(Line1, (unsigned char *)"        Data       ");
sprintf(cnbr_lcd,"    CNBR:%d          ",cnbr);
LCD_DisplayStringLine(Line3, (unsigned char *)cnbr_lcd);
//单字符高亮
if(flag == 1&&set_flag) LCD_SetBackColor(Blue);//状态1-Seeting状态 高亮显示小时
	LCD_DisplayChar(Line4 , (320 - (16 * 6)) , hour/10 + 0x30);
	LCD_DisplayChar(Line4 , (320 - (16 * 7)) , hour%10 + 0x30);
	LCD_SetBackColor(Black);
	
	LCD_DisplayChar(Line4 , (320 - (16 * 8)) , ':');
	
if(flag == 2&&set_flag) LCD_SetBackColor(Blue); //状态2-Seeting状态 高亮显示分钟
	LCD_DisplayChar(Line4 , (320 - (16 * 9)) , min/10 + 0x30);
	LCD_DisplayChar(Line4 , (320 - (16 * 10)) , min%10 + 0x30);
	LCD_SetBackColor(Black);
	
	LCD_DisplayChar(Line4 , (320 - (16 * 11)) , ':');

if(flag == 3&&set_flag) LCD_SetBackColor(Blue); //状态3-Seeting状态 高亮显示秒
	LCD_DisplayChar(Line4 , (320 - (16 * 12)) , s/10 + 0x30);
	LCD_DisplayChar(Line4 , (320 - (16 * 13)) , s%10 + 0x30);
	
	LCD_SetBackColor(Black);

七、adc输入 与dac输出

adc输入

官方一般使用PB15引脚

//adc
double rd_adc(ADC_HandleTypeDef* hadc)
{
	unsigned int adc_data=0;
	HAL_ADC_Start(hadc);
	adc_data=HAL_ADC_GetValue(hadc);
	return adc_data*3.3/4096;
}

dac输出

HAL_DAC_Start(&hdac1,DAC_CHANNEL_1); // main函数使能DAC1的通道1
DAC1_Set_Vol(1.50);   // 调用DAC1设置电压函数
void DAC1_Set_Vol(float vol)
{
	uint32_t temp;  //  定义电压转换后的数值
	temp = (4096 * vol/3.3f);  //  12位的DAC最大数值为4096,vol / 3.3 就是设置的电压所占全部电压(3.3V)的比例
	HAL_DAC_SetValue(&hdac1, DAC_CHANNEL_1,DAC_ALIGN_12B_R,temp); // 最终的电压设置函数
}

八、iic—–eeprom

main函数调用

I2CInit();//初始化

以下为连读连写代码

void byte_write(uint8_t addr,uint8_t *data){
		I2CStart();
		I2CSendByte(0xa0);
		I2CWaitAck();
		I2CSendByte(addr);
		I2CWaitAck();
		I2CSendByte(data[0]);
		I2CWaitAck();
		I2CSendByte(data[1]);
		I2CWaitAck();
		I2CSendByte(data[2]);
		I2CWaitAck();
		I2CStop();
}

void read(uint8_t addr ,uint8_t *data)
{
	I2CStart();
	I2CSendByte(0xa0);
	I2CWaitAck();
	I2CSendByte(addr);
	I2CWaitAck();
	I2CStart();//重新开始
	I2CSendByte(0xa1);
	I2CWaitAck();
	data[0]=I2CReceiveByte();
	I2CSendAck();//发送响应
	data[1]=I2CReceiveByte();
	I2CSendAck();
	data[2]=I2CReceiveByte();
    I2CSendNotAck();
	I2CStop();
}

iic——eeprom存入浮点数

				extern double x_1,y_1;
				uint8_t data[4]={0};
//写入
				data[2]=(uint8_t)(x_1*10);
				data[3]=(uint8_t)(y_1*10);
				wite(0,data);
//读取
				read(0,data);
				x_1=data[2]/10.0;
				y_1=data[3]/10.0;

九、定时器

配合定时器使用

	if(s==0) 
            { 
                if(min!=0||hour!=0)	
                {
                    s=59;
					  if(min!=0)	   
                          min-=1;
					  else if(hour!=0) 
                      { 
                          min=59;
                          hour-=1; 
                      }
				}
			}else if(s!=0)	
                s-=1;

		if(flag==1)      { hour+=1;  if(hour>59) hour=0;}
		else if(flag==2) { min+=1;   if(min>59)  min=0; }
		else if(flag==3) { s+=1;     if(s>59)    s=0;   }

十、rtc

 

 

RTC_TimeTypeDef stime;
RTC_DateTypeDef sdate;
void get_time (void)
{
	HAL_RTC_GetTime(&hrtc, &stime, RTC_FORMAT_BIN);
	HAL_RTC_GetDate(&hrtc, &sdate, RTC_FORMAT_BIN);
}
sprintf(time,"      %d:%d:%d        ",stime.Hours,stime.Minutes,stime.Seconds);
LCD_DisplayStringLine(Line7, (uint8_t *)time);

十一、冒泡排序

void lit(void)
{
	uint8_t i, j, temp;
	hight[0]=threshold1_data;
	hight[1]=threshold2_data;
	hight[2]=threshold3_data;
	for (i = 1; i <= 2; i++)//外部总共要遍历n-1次(n为元素个数)
	{
		for (j = 0; j <= 2 - i; j++)//每一次将最大值放在最后以后,前面的数两者比较次数-1
		{
			if (hight[j] > hight[j + 1])
			{
				temp = hight[j];
				hight[j] = hight[j + 1];
				hight[j + 1] = temp;
			}
		}
	}
}

作者:浇头硬件

物联沃分享整理
物联沃-IOTWORD物联网 » 蓝桥杯嵌入式省赛考点模块最简书写方式详解

发表评论