由硬件框圖可以知道我們要配置LED 和按鍵
LED
先配置LED的八個引腳為GPIO_OutPut,鎖存器PD2也是,然后都設置為起始高電平,生成代碼時還要去解決引腳沖突問題
按鍵
按鍵配置,由原理圖按鍵所對引腳要GPIO_Input
生成代碼,在文件夾中添加code文件夾,code中添加fun.c、fun.h、headfile.h文件,去資源包中把lcd.c、lcd.h、fonts.h添加到code中,然后去寫按鍵控制燈亮滅的程序,看是否有問題
按鍵控制led沒有問題后寫lcd顯示代碼,顯示沒問題后,解決lcd與led引腳沖突問題,方法在我的其他文章中
? HAL_GPIO_WritePin (GPIOD,GPIO_PIN_2,GPIO_PIN_RESET ); //為解決引腳沖突初始化lcd時? ??LCD_Init (); ? ? ? ? ? ?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 要將鎖存器鎖存器來;
? LCD_Clear (Black);
? LCD_SetBackColor(Black);
? LCD_SetTextColor(White);
LCD顯示函數
void lcd_show(void)
{
?? ?sprintf(text," ? ? ?hello world");
?? ?LCD_DisplayStringLine (Line0 ,(uint8_t *)text);
}
eeprom
用到eeprom就要用到IIC通信協議就要去資源包中將IIC_hal.c? ?IIC_hal.h添加進來
然后再main中方初始化IIC
然后寫eeprom讀和寫的函數,用lcd顯示測試功能是否好用,沒有問題就開始寫ADC的功能函數代碼。
ADC
由原理圖知道ADC測量是由PB15與PB12測量,去配置兩引腳為ADCx_INx,去相應ADCx中勾選相對應的INx為single-ended,后編寫電壓獲取函數,其中用到ADC測量量與電壓轉化公式。
上面把需要用的功能都測試了一次沒有問題,就開始按要求寫寫代碼
下面是分別界面顯示的代碼
void Lock_show(void)
{
? sprintf(text," ? ? ? ?Lock ? ? ? ?" );
?? ?LCD_DisplayStringLine (Line2 ,(uint8_t *)text);
?? ?
? sprintf(text," ? ? ?Pass Word ? ? " ?);
?? ?LCD_DisplayStringLine (Line4 ,(uint8_t *)text);
?? ?
? sprintf(text," ? ? ? ?* * * ? ? ? " ?);
?? ?LCD_DisplayStringLine (Line5 ,(uint8_t *)text);
?? ?
}
void Set_show(void)
{
? sprintf(text," ? ? ? ?Set ? ? ? ? " );
?? ?LCD_DisplayStringLine (Line2 ,(uint8_t *)text);
?? ?
? sprintf(text," ? ? ? Change ? ? ? " ?);
?? ?LCD_DisplayStringLine (Line4 ,(uint8_t *)text);
?? ?
? sprintf(text," ? ? ? * * * ? ? ? ?" ?);
?? ?LCD_DisplayStringLine (Line5 ,(uint8_t *)text);
?? ?
}
ADC電壓值轉換成數值密碼,將i輸出到屏幕就行
void Lock_show(void)
{
?? ?if(get_vo1(&hadc2)<1.5)
?? ?{
?? ??? ?i=0;
?? ?}
?? ?else if(1.5<get_vo1(&hadc2)&&get_vo1(&hadc2)<2.5)
?? ?{
?? ??? ?i=1;
?? ?}
?? ?else
?? ?{
?? ??? ?i=2;
?? ?}
*按鍵與電壓共同輸入密碼
限定電壓的大小可以控制輸入的數字為0 1 2,密碼一共有三位,這就需要輸入第一位后記住并且切換到下一位,切換就需要用到按鍵,按鍵按一下且為下一位,再按一下又切換到下一位,再按又回到第一位輸入。寫代碼時參數跨文件使用的就要在.h中外部申明,外部聲明的數組在.c中初始化就不可以在.h又初始化
案件代碼
uint8_t count;
uint8_t Password[3]={0,1,2};
uint8_t word[3];用于記住輸入的密碼//這三個都需要外部聲明void key_scan(void)
{B1_state=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);if(B1_state==0&&B1_last_state==1) //如果按下就用word[]記住當前數值{if(get_vo1(&hadc2)<1.5){word[count]=0;}else if(1.5<get_vo1(&hadc2)&&get_vo1(&hadc2)<2.5){word[count]=1;}else{word[count]=2;}count++;count %=3;}B1_last_state=B1_state;
}
輸入密碼顯示
void Lock_show(void)
{sprintf(text," Lock " );LCD_DisplayStringLine (Line2 ,(uint8_t *)text);sprintf(text," Pass Word " );LCD_DisplayStringLine (Line4 ,(uint8_t *)text);if(get_vo1(&hadc2)<1.5){if(count==0){sprintf(text," %d * * ",0 );}else if(count==1){sprintf(text," %d %d * ",word[0],0);}else if(count==2){sprintf(text," %d %d %d ",word[0],word[1],0 );}LCD_DisplayStringLine (Line5 ,(uint8_t *)text);}else if(1.5<get_vo1(&hadc2)&&get_vo1(&hadc2)<2.5){if(count==0){sprintf(text," %d * * ",1 );}else if(count==1){sprintf(text," %d %d * ",word[0],1);}else if(count==2){sprintf(text," %d %d %d ",word[0],word[1],1 );}LCD_DisplayStringLine (Line5 ,(uint8_t *)text);}else{if(count==0){sprintf(text," %d * * ",2 );}else if(count==1){sprintf(text," %d %d * ",word[0],2);}else if(count==2){sprintf(text," %d %d %d ",word[0],word[1],2);}LCD_DisplayStringLine (Line5 ,(uint8_t *)text);}
}
用一個標志位來修改頁面,當密碼正確時標志位改變,進入修改頁面
uint8_t show_flag;// 標志位,0位輸出頁面,1位修改頁面
if(word[0]==Password[0]&&word[1]==Password[1]&&word[2]==Password[2])
?? ??? ??? ??? ?{
?? ??? ??? ??? ??? ?show_flag=1;
?? ??? ??? ??? ?}
進入修改頁面后重新輸入密碼,并把修改后的密碼覆蓋掉原來的密碼,這時候就需要區分頁面,輸出頁面輸入三位密碼后進行判斷密碼是否正確,修改頁面就進行密碼覆蓋和存到eeprom中(題目要求),下面是頁面區分代碼
if(B1_state==0&&B1_last_state==1){if(show_flag==0){if(get_vo1(&hadc2)<1.5){word[count]=0;}else if(1.5<get_vo1(&hadc2)&&get_vo1(&hadc2)<2.5){word[count]=1;}else{word[count]=2;}if(count==2){if(word[0]==Password[0]&&word[1]==Password[1]&&word[2]==Password[2]){show_flag=1;}}count++;count %=3;}else if(show_flag==1){if(get_vo1(&hadc2)<1.5){word[count]=0;}else if(1.5<get_vo1(&hadc2)&&get_vo1(&hadc2)<2.5){word[count]=1;}else{word[count]=2;}if(count==2){}}}
在修改頁面中判斷是否輸入三位數密碼后進行密碼修改與存儲,其中在進入修改頁面后還要進行是否三秒問操作。
修改密碼,進入修改頁面后,輸入了新的三位密碼后進行密碼修改
? ? ? ? ? ?if(count==2)? //判斷是否輸入了新的三位密碼
?? ??? ??? ??? ?{
?? ??? ??? ??? ??? ?for(i=0;i<3;i++)
?? ??? ??? ??? ??? ?{
?? ??? ??? ??? ??? ??? ?Password[i]=word[i];
?? ??? ??? ??? ??? ?}
? ? ? ? ? ? ? ? ? ? ??save_password();
? ? ? ? ? ? ? ? ? ? ? show_flag=0;密碼修改好后回到輸出頁面
?? ??? ??? ??? ?}
把密碼存到eeprom中還需寫一個人寫入函數,??eeprom_write函數上面我們已經寫過了,寫好后在修改密碼后調用,上面紅色代碼就是調用,在main中也要調用,題目要求一開始的初始密碼也是存到eeprom中
void save_password()
{
??eeprom_write(0x00,Password[0]);
? eeprom_write(0x01,Password[1]);
? eeprom_write(0x02,Password[2]);
}
到此基本功能完成,這時還有個進入修改界面三秒不操作返回原界面功能,指示燈沒有寫。計算三秒需用到定時器,要配置一下,三秒跳轉可以用時間標志位進行實現功能。定時器我這配置10ms的,計算公式位系統頻率(PSC+1)*(ARR+1)/Fsys,所以RSC=8000-1,ARR100-1記得開啟中斷。生成代碼記得把.h包含進去
要在maim中開啟時鐘? ? HAL_TIM_Base_Start_IT(&htim4);有中斷要用IT的
?
之后去找回調函數void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)寫函調函數
htim->Instance這是指向定時器的句柄指針?
作用
1.標識具體的定時器實列
2.參數配置和操作
3.中斷處理
初始化一個定時器于啟用的列子
TIM_HandleTypeDef htim2;
void MX_TIM2_Init(void)
{
? ? htim2.Instance = TIM2; // 指定定時器實例為TIM2
? ? htim2.Init.Prescaler = 36000 - 1; // 設置預分頻值
? ? htim2.Init.CounterMode = TIM_COUNTERMODE_UP; // 設置計數模式為向上計數
? ? htim2.Init.Period = 2000 - 1; // 設置周期值
? ? htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; // 時鐘分頻因子
? ? if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
? ? {
? ? ? ? Error_Handler();
? ? }
}
配置好定時器后把標志位寫到判斷密碼正確的if語句中,并且賦值
定期進行及時,如果3秒后沒有進行操作,返回輸入頁面
根據最后的要求,輸入界面led1亮,否則滅
? ? ? ? ? ? ? ? ? ? ? ? ? ? 修改界面led2亮,否則滅