原來在實習的時候公司要求IO口的分時復用,按鍵與數碼管顯示
這里用stm32和仿真想簡單實現一下,但是不太成功,希望有大神指點。后面也會陸續更新各種按鍵方法和不同的數碼管
大概的方法就是用定時器不斷地去切換IO口的狀態,讀取按鍵的時候把鍵值保存,數碼管顯示的時候顯示,一直反復
#include "stm32f10x.h"
char flag;
u16 table[]={0x3f,0x30,0x6d,0x79,0x72,0x5b,0x5f,0x31,0x7f,0x7b,0x77,0x5e,0x0f,0x7c,0x4f,0x47};
void delay(u8 cnt)
{int i,j;
for(i=0;i<cnt;i++)
{
for(j=0;j<10000;j++){;}
}
}
void TIM2_Init(u16 CNT)
{//初始化
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //時鍾使能
TIM_TimeBaseStructure.TIM_Period = CNT-1; //重裝值,
TIM_TimeBaseStructure.TIM_Prescaler =7200-1; //分頻系數,72M/7200=10KHz,其他依此類推
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //設置時鍾分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上計數模式
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //把上述數值寫入對應寄存器
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE); //使能或者失能指定的TIM中斷
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; //TIM2中斷
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占優先級0級
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //從優先級3級
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure); //把上述數值寫入對應寄存
TIM_Cmd(TIM2, ENABLE); //使能TIM2
}
void My_GPIO_Init_LED(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All; //設定要操作的管腳
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; //設置為推挽輸出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // IO口速度為50MHz
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
void My_GPIO_Init_KEY(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All; //設定要操作的管腳
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // IO口速度為50MHz
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
int main()
{int i;
u16 keycode;
TIM2_Init(500);//50ms中斷一次
while(1)
{GPIO_ResetBits(GPIOA,GPIO_Pin_7);
if(flag==1)
{
My_GPIO_Init_KEY();
keycode=GPIO_ReadInputData(GPIOA);
flag=0;
}
My_GPIO_Init_LED();
switch(keycode)
{
case 0x00FE: GPIO_Write(GPIOA,table[1]); break;
case 0x00FD:GPIO_Write(GPIOA,table[2]); break;
case 0x00FB:GPIO_Write(GPIOA,table[3]); break;
case 0x00F7:GPIO_Write(GPIOA,table[4]); break;
case 0x00EF:GPIO_Write(GPIOA,table[5]); break;
case 0x00DF:GPIO_Write(GPIOA,table[6]); break;
case 0x00BF:GPIO_Write(GPIOA,table[7]); break;
default :GPIO_Write(GPIOA,table[0]);
}
}
}
void TIM2_IRQHandler(void)//每次產生一個中斷溢出事件就會進入一次中斷函數
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)//檢測是否為溢出中斷
{
GPIO_SetBits(GPIOA,GPIO_Pin_7);
flag=1;
delay(100);
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);//清除中斷標志位,否則啟動時會進入中斷服務函數
}
}