老规矩,先看外设要求...... ADC,LED,LCD,KEY,EEPROM。除了EEPROM之外其它没什么新意,所以我们来看看EEPROM就可以了(其它可以在第一套模拟题中看到)
/*****************************************************************************************************************/
EEPROM配置本来是需要写IIC驱动代码的,但赛方给了,我们就不浪费时间了。
直接调用里面的函数来完成我们要的功能就行
我们需要什么功能? ------一个数据写入,一个数据读取
就这两个功能,没有其它的了(当然还有初始化)。
void E2P_Init() {
//初始化直接调用给的初始化函数即可 I2CInit(); }
接下来是数据写入功能
//写入数据需要什么? -待写入的数据的地址DataAddr,要写入的数据量Count,以及要在芯片中存储的地址空间Store_Addr
uint8_t E2P_Write(uint8_t * DataAddr,uint8_t Count,uint8_t *Store_Addr) { I2CStart(); //启动IIC传输 I2CSendByte(0xa0); //发送操作码(不同厂家对其芯片都会有一套操作码来执行不同的芯片功能,如这里0xa0是写入的操作码 0xa1是读取当前地址数据的操作码) while(I2CWaitAck()!=0); //等待应答(阻塞写法不可取...........不要学我) I2CSendByte(*Store_Addr); //发送要存储在芯片的地址位置,这里我会用到0位置 while(I2CWaitAck()!=0); while(--Count) //传输Count个字节的数据 { I2CSendByte(*DataAddr++); //发送要写入的数据 while(I2CWaitAck()!=0); } I2CStop(); //结束IIC传输 HAL_Delay(200); //这里实际测试的时候需要一些延时 }
再之是数据读取功能
//读取数据需要什么? -存放数据的地址DataAddr,要读取的数据量Count,以及要在芯片中读取的地址空间Store_Addr
uint8_t E2P_Read(uint8_t * DataAddr,uint8_t Count,uint8_t *Store_Addr) { I2CStart();
//为什么这里是写入操作码0xa0? ------由于芯片上电默认是从0位置处开始读取数据,但我们要访问其它地址数据就需要先通过写入来改变当前芯片内部自增指针的指向 I2CSendByte(0xa0); while(I2CWaitAck()!=0); I2CSendByte(*Store_Addr); //使指针指向要读取的数据地址 while(I2CWaitAck()!=0) ; I2CStart(); //重新启动传输 I2CSendByte(0xa1); //读取操作码 while(I2CWaitAck()!=0) ; while(Count) { *DataAddr++ = I2CReceiveByte(); //从芯片内读取字节数据 if(--Count) //当Count非0时返回应答,否则返回非应答 I2CSendAck(); } I2CSendNotAck(); I2CStop(); HAL_Delay(200); }
至此,EEPROM的基本功能就已经完成了,下一步就是去实现代码逻辑。
/********************************************************************************************************/
由题目需求需要对ADC值进行计算,我们定义一些变量来完成这个功能
#include "bsp/adc_proj.h" float Caculate_ADC1,Caculate_ADC2,Caculate_Result; //采集ADC1,ADC2锁定和计算后的结果(题目要求是按下按键后锁定当前时刻ADC值) uint8_t Caculate_Mode = Cal_ADD; //计算模式两种 Cal_ADD(1) ,Cal_DEC(0) uint8_t ADC1_G,ADC2_G; //两个标志位确定ADC值是否已经锁定 uint8_t ADC_Calculate() { if(ADC1_G == 0 || ADC2_G == 0 ) //如果没有锁定,直接返回0,无法计算 return 0; else { ADC1_G = ADC2_G = 0; //重置锁定 if(Caculate_Mode == Cal_ADD ) Caculate_Result = Caculate_ADC1 + Caculate_ADC2; else Caculate_Result = Caculate_ADC1 - Caculate_ADC2; } return 1; //返回1,表示计算成功 }
回到main函数中先对ADC进行初始化,在while中不断采集ADC值并通过计算得到计算结果给后续LCD输出
int main(void) { MX_ADC1_Init(); MX_ADC2_Init(); while(1) {
My_ADC_Get();
if(ADC_Calculate() == 1) Cal_Cmd = 1; //Cal_Cmd:作用是在LCD中区分输出ERROR还是数值
}
/**********************************************************************************************************************/
再来完成LED的要求
#include "gpio.h" #include "BSP/led_proj.h" //需要判断当前的LCD_Mode和ADC计算的结果Result void LED_SHOW(uint8_t LCD_Mode,float Result) { HAL_GPIO_WritePin(GPIOC, LED6_Pin|LED7_Pin|LED8_Pin|LED1_Pin |LED2_Pin|LED3_Pin|LED4_Pin|LED5_Pin, GPIO_PIN_SET); if(LCD_Mode == DATA) //数据界面LED1点亮 My_Led_On(LED1,1); else My_Led_On(LED1,0); if(LCD_Mode == Caculate)//同上 My_Led_On(LED2,1); else My_Led_On(LED2,0); if(Result > 6) //计算值大于6时,闪烁LED3 My_Led_Flash(); else My_Led_On(LED3,0); //锁存器锁存 HAL_GPIO_WritePin(LED_Cmd_GPIO_Port, LED_Cmd_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(LED_Cmd_GPIO_Port, LED_Cmd_Pin, GPIO_PIN_RESET); }
/************************************************************************************************************************/
LCD显示部分
#include "BSP/lcd_proj.h" uint8_t LCD_Mode = DATA; //当前LCD显示 uint8_t LCD_str[255]; uint8_t Cal_Cmd; //是否有计算结果(是否有锁存数据) void DATA_SHOW(float ADC1_3_3,float ADC2_3_3) {
//显示ADC1,ADC2的实时采集值 LCD_Clear(Black); sprintf((char *)LCD_str," DATA"); LCD_DisplayStringLine(Line2,LCD_str); sprintf((char *)LCD_str,"R37:%1.2fV",ADC1_3_3); LCD_DisplayStringLine(Line3,LCD_str); sprintf((char *)LCD_str,"R38:%1.2fV",ADC2_3_3); LCD_DisplayStringLine(Line4,LCD_str); } void Caculate_SHOW(float Cal_Value,uint8_t Cal_Mode) {
//显示锁存数据后的计算结果和当前计算模式 LCD_Clear(Black); sprintf((char *)LCD_str," COU"); LCD_DisplayStringLine(Line2,LCD_str); if(Cal_Cmd == 1) //全部锁存 { sprintf((char *)LCD_str,"RES:%1.2fV",Cal_Value); LCD_DisplayStringLine(Line3,LCD_str); } else //没有全部锁存,直接返回Error { sprintf((char *)LCD_str,"RES:Error"); LCD_DisplayStringLine(Line3,LCD_str); } sprintf((char *)LCD_str,"MODE:%d",Cal_Mode); LCD_DisplayStringLine(Line4,LCD_str); } void LCD_Show(float ADC1_3_3,float ADC2_3_3,float Cal_Value,uint8_t Cal_Mode) { if(LCD_Mode == DATA) DATA_SHOW( ADC1_3_3, ADC2_3_3); else Caculate_SHOW(Cal_Value,Cal_Mode); }
接下来在main函数中完成其它功能的逻辑
int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); //LED.KEY初始化 MX_ADC1_Init(); //ADC初始化 MX_ADC2_Init();
E2P_Init(); //EEPROM初始化 E2P_Read(&Caculate_Mode,1,0); //每次上电从0地址处读取当前的计算模式 -------这里不知道为什么一直读出来是255,后面找一下这个DEBUG......
//LCD初始化配置 LCD_Init(); LCD_SetBackColor(Black); LCD_SetTextColor(White); while (1) { Key_Value = My_Key_Get(); //采集按键值 if(Key_Value == KEY1) //数据界面按下KEY1 ->锁存ADC1的值 { if(LCD_Mode == DATA) { Caculate_Result = 0; Cal_Cmd = 0; ADC1_G = 1; Caculate_ADC1 = ADC1_3_3; } } else if(Key_Value == KEY2) //同上 { if(LCD_Mode == DATA) { Caculate_Result = 0; Cal_Cmd = 0; ADC2_G = 1; Caculate_ADC2 = ADC2_3_3; } } else if(Key_Value == KEY3) //按下KEY3,切换LCD界面 LCD_Mode ^=1; else if(Key_Value == KEY4) //按下KEY4,切换数据计算模式 { if(LCD_Mode == Caculate) { if(Caculate_Mode == Cal_ADD) Caculate_Mode =Cal_DEC; else Caculate_Mode =Cal_ADD; E2P_Write(&Caculate_Mode,1,0); } }
//采集并计算ADC值 My_ADC_Get(); if(ADC_Calculate() == 1) Cal_Cmd = 1; //LCD和LED显示 LCD_Show(ADC1_3_3,ADC2_3_3,Caculate_Result,Caculate_Mode); LED_SHOW(LCD_Mode,Caculate_Result); } }
模拟题相较真题来说,逻辑简单很多,后面来做真题看看吧。
标签:14,Caculate,ADC1,模拟题,蓝桥,LCD,ADC2,Mode,Cal From: https://www.cnblogs.com/sujian4412/p/18085654