IO口分时复用的简单实现

原来在实习的时候公司要求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);//清除中断标志位,否则启动时会进入中断服务函数
    }
}

原文地址:https://www.cnblogs.com/wulianwangaxing/p/14394616.html