蓝桥杯嵌入式第十三届省赛

整体架构流程

1.外设初始化

大体浏览程序设计可知,我们所需要初始化的外设有:LED、PWM、USART、按键这四个外设的端口,EEPROM有蓝桥杯大赛官方准备的i2C-hal.c和i2C-hal.h文件,实验不需要我们去初始化,初始文件也是采用hal库的液晶驱动程序。

USART我们需要调节成异步模式,波特率为9600bit/s

通过题目可知,我们需要使PA1输出2000Hz的频率,且初始占空比为5%

2.LCD界面显示

void LCD_Process()
{
	u8 diaplay_buf[20];//存储显示数据
	if(DISPLAY_MODE==DISPLAY_SHOP)
	{
		LCD_DisplayStringLine(Line2, (uint8_t *)"        SHOP      ");
	
		sprintf((char *)diaplay_buf,"     X:%-2d",Xs);
		LCD_DisplayStringLine(Line4,(uint8_t *)diaplay_buf);
		
		sprintf((char *)diaplay_buf,"     Y:%-2d",Ys);
		LCD_DisplayStringLine(Line5,(uint8_t *)diaplay_buf);
	}
	else if(DISPLAY_MODE==DISPLAY_PRICE)
	{
		LCD_DisplayStringLine(Line2, (uint8_t *)"        PRICE      ");
	
		sprintf((char *)diaplay_buf,"     X:%-2.1f",Xv/10.0f);
		LCD_DisplayStringLine(Line4,(uint8_t *)diaplay_buf);
		
		sprintf((char *)diaplay_buf,"     Y:%-2.1f",Yv/10.0f);
		LCD_DisplayStringLine(Line5,(uint8_t *)diaplay_buf);
	}
	else 
	{
		LCD_DisplayStringLine(Line2, (uint8_t *)"        REP      ");
	
		sprintf((char *)diaplay_buf,"     X:%-2d",Xn);
		LCD_DisplayStringLine(Line4,(uint8_t *)diaplay_buf);
		
		sprintf((char *)diaplay_buf,"     Y:%-2d",Yn);
		LCD_DisplayStringLine(Line5,(uint8_t *)diaplay_buf);
	}
}

为了更加简洁方便的显示数据,我们可以通过sprintf()函数将数据写入到一个数组中进行间接的输出

3.按键

void Key_Process()
{
	if(uwTick - KEYTICK < 20) return;
	KEYTICK=uwTick;
	Key_Read();
	if(Trg & 0x01)
	{
		LCD_Clear(Black);
		DISPLAY_MODE=(DISPLAY_MODE + 1 ) % 3;
	}
	if(Trg & 0x02)
	{
		if(DISPLAY_MODE==DISPLAY_SHOP)
		{
			Xs=(Xs + 1)%(Xn+1);
		}
		else if(DISPLAY_MODE==DISPLAY_PRICE)
		{
			Xv++;
			if(Xv==21) {Xv=10;}
			
		}
		else if(DISPLAY_MODE==DISPLAY_REP)
		{
			Xn++;
			
		}
	}
	if(Trg & 0x04)
	{
		if(DISPLAY_MODE==DISPLAY_SHOP)
		{
			Ys=(Ys + 1)%(Yn+1);
		}
		else if(DISPLAY_MODE==DISPLAY_PRICE)
		{
			Yv++;
			if(Yv==21) {Yv=10;}
			
		}
		else if(DISPLAY_MODE==DISPLAY_REP)
		{
			Yn++;
			
		}
	}
	if(Trg & 0x08)
	{
		if(DISPLAY_MODE==DISPLAY_SHOP)
		{
			if(Xn >= Xs || Yn >= Ys)
			{
				Xn=Xn-Xs;
				Yn=Yn-Ys;
				Xs=0;Ys=0;
				
			
			}
		}
	}
}

程序设计要求B1可以实现三个届面的切换,所以我们需要定义一个变量ru:DISPLAY_MODE,来表示届面,还需要定义三个parameter常量表示购买界面、单价界面和库存界面;

B2则需要实现商品X在三个界面下的调试,如:在购买界面按一下B2则购买数量加1,在单价界面按一下B2则单价+0.1,在库存界面则是库存数量加1

B3功能和B2一样代表商品Y

B4表示确认购买商品

4.EEPROM的读写

void EEPROM_Process()
{
		if(EEPROM_Read(0xf0)!= 0xa0)
		{
				EEPROM_Write(0xf0,0xa0);
				EEPROM_Write(0x00,Xn);
				EEPROM_Write(0x01,Yn);
				EEPROM_Write(0x02,Xv);
				EEPROM_Write(0x03,Yv);
		}
		Xn = EEPROM_Read(0x00);
		Yn = EEPROM_Read(0x01);
		Xv = EEPROM_Read(0x02);
		Yv = EEPROM_Read(0x03);
}

这是检查EEPROM是否是第一次上电,如果是则写入初始数据,如果不是则读取数据

根据要求可知,我们需要在库存数量和价格在变化的时候写入,不变化的时候不变化,所以我们需要在按键按下去的时候就写入数据,例如:

if(Trg & 0x02)
	{
		if(DISPLAY_MODE==DISPLAY_SHOP)
		{
			Xs=(Xs + 1)%(Xn+1);
		}
		else if(DISPLAY_MODE==DISPLAY_PRICE)
		{
			Xv++;//单价改变
			if(Xv==21) {Xv=10;}
			EEPROM_Write(0x02,Xv);
		}
		else if(DISPLAY_MODE==DISPLAY_REP)
		{
			Xn++;
			EEPROM_Write(0x00,Xn);//库存数量改变
		}
	}

5.PWM输出

PWM输出只需要改变占空比即可

void PWM_Process()
{
	if(led_flag==1)
	{
		TIM2->CCR2=150;
	}
	else
		TIM2->CCR2=25;
}

6.LED闪烁

void Led_Process()
{
	if(led_flag==1)
	{
		led_Ctrl |=0x01;
		cnt_5s++;
		if(cnt_5s==5000)
		{
			cnt_5s=0;
			led_flag=0;
			led_Ctrl &=~0x01;
		}
	}
	if(Xn==0 && Yn==0)
	{
		cnt_1 = cnt_1%200 +1;
		if(cnt_1 <= 100)
			led_Ctrl |=0x02;
		else
			led_Ctrl&=~0x02;
	}
	else
		led_Ctrl&=~0x02;
	
}

led1在确认购买商品后亮5秒,即B4按下后亮5秒,我们可以通过systick来计数

led2是X和Y的库存数量为零是以0.1秒为间隔进行闪烁,也可以用systick来计数

void SysTick_Handler(void)//1ms
{
  /* USER CODE BEGIN SysTick_IRQn 0 */

  /* USER CODE END SysTick_IRQn 0 */
  HAL_IncTick();
  /* USER CODE BEGIN SysTick_IRQn 1 */

  /* USER CODE END SysTick_IRQn 1 */
}

7.USART的发送和接收

int fputc(int ch, FILE *f)//重定向
{
  HAL_UART_Transmit(&huart1,(unsigned char *)ch,1,50);
  return(ch);
}

u8 uart_buf[20];
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	HAL_UART_Receive_IT(&huart1,uart_buf,1);
	if(uart_buf[0] == '?')
	{
		printf("X:%.1f,Y:%.1f",Xv/10.0f,Yv/10.0f);
	}
}

对串口的发送我们可以进行printf的重定向,这样我们就可以通过printf来发送数据

技术细节

1.在调用void SysTick_Handler(void)时我们需要在stm32xxxxit.c把它屏蔽,否则会发生冲突代码会报错

2.LED的处理函数我们可以放在SysTick_Handler()中,如果直接将LED_Procrss()放在main函数中会和LCD发生冲突,代码是不会报错的,但是液晶显示的时候会用一些明显的小点,控制单个led亮灭的函数放在while中

结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值