TM1618扫描按键问题

2019-08-17 09:34发布

本人用STM32F103RCT6进行数码管的实验,试验中,数码管显示无问题(即MCU与1618的通讯没有问题),但是按键扫描一直不能成功。特开此帖请教!!!
以下是原理图
QQ截图20170328112739.png
以下是TM1618.c文件的全部代码
#include "tm1618.h"
#include "delay.h"
#include "usart.h"       
/*
* DIO引脚用的PB5,CLK引脚用PB4,STB引脚用PB3
*****************************************************/
void        tm1618_clear(void);
void        tm1618_WrByte(u8 oneByte);
void         tm1618_DisPlay(void);
u8                 tm1618_ScanKey(void);

/*****************************************************
* name:        tm1618_init
* param:
* return:
* desc:        驱动芯片初试化,先把所有的显示清零
**************************************************/
void tm1618_init(void)
{
        u8 data0[4] = {0,1,2,3};
        u8 data1[4] = {4,5,6,7};
        u8 data2[4] = {8,9,0,1};
        u8 i;
        u8 key;
        GPIO_InitTypeDef GPIO_InitStructure;
       
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);

        GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);//关闭jtag,使能SWD,可以用SWD模式调试

        // 如果要输出为5V,可以用开漏输出,不能用推挽输出
        // PB3.4可以耐受5V,PB5不能耐受5V
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 ;
//        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;                // 复用开漏输出
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;        // 开漏输出
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOB, &GPIO_InitStructure);
       
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;        // 通用推挽输出
        GPIO_Init(GPIOB, &GPIO_InitStructure);

        TM1618_DIO = 1;
        TM1618_CLK = 1;
        TM1618_STB = 1;
       
        delay_us(2);

        tm1618_DisPlay();        // 设置显示模式
        tm1618_clear();                // 清除所有显示
       
       
        while(1){
                switch(i){
                        case 0:
                                tm1618_DisData(data0);
                                break;
                        case 1:
                                tm1618_DisData(data1);
                                break;
                        case 2:
                                tm1618_DisData(data2);
                                break;
                }
                key = tm1618_ScanKey();
                if( key != 0 ){        // 如果有按键按下,则改变显示内容
                        i++;
                }
                if(i == 3){
                        i = 0;
                }
                delay_ms(5000);
                delay_ms(60000);
        }
       
}

/*****************************************************
* name:        tm1618_WrByte
* param:
* return:
* desc:        写一个字节,字节按照MSB来写,发送按照LSB发送
**************************************************/
void tm1618_WrByte(u8 oneByte){
        u8 i;
        for(i = 0;i < 8;i++){
                TM1618_CLK = 0;
                if(oneByte & 0x01){        // 低位在前
                        TM1618_DIO = 1;
                }else{
                        TM1618_DIO = 0;
                }
                delay_us(3);
                oneByte = oneByte>>1;
                TM1618_CLK = 1;
                delay_us(3);
        }
}

/*****************************************************
* name:        tm1618_clear
* param:
* return:
* desc:        清除数码管显示的数字
**************************************************/
void tm1618_clear(void){
        u8 i;
        u8 byte;
       
        byte = 0x40;        // 数据命令,写数据到显示寄存器,自动地址增加
        TM1618_STB = 0;
        tm1618_WrByte( byte );       
        TM1618_STB = 1;
        delay_us(3);
       
        byte = 0xc0;        // 显示地址从0xc0开始
        TM1618_STB = 0;
        tm1618_WrByte( byte );       
        byte = 0x00;        // 写入数据,全部写为0
        for(i = 0; i < 14; i++){
                tm1618_WrByte( byte );               
        }
        TM1618_STB = 1;
        delay_us(3);
       
        byte = 0x8f;        // 显示开关开,辉度为最亮14/16
        TM1618_STB = 0;
        tm1618_WrByte( byte );       
        TM1618_STB = 1;
        delay_us(3);
}

/*****************************************************
* name:        tm1618_ScanKey
* param:
* return:SUCCESS:有按键按下
*                ERROR: 无按键按下
* desc:        读按键,只需要关心K1即可
**************************************************/
u8 tm1618_ScanKey(void){
        u8 status = ERROR;
        u8 byte = 0x42;        // 读键扫程序
        u8 i,j;
        GPIO_InitTypeDef GPIO_InitStructure;        // PB5要改成输入
       
        u8 temp;
       
        TM1618_STB = 0;       
        tm1618_WrByte( byte );
        TM1618_DIO = 1;
        // 如果DIO用开漏输出,可以直接用GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0)读IO的值
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;        // 下拉输入
        GPIO_Init(GPIOB, &GPIO_InitStructure);
        //
        delay_us(2);        // 在第八个时钟下降沿之后延时5us,开始判断ACK信号
        for(i=0; i<3;i++){
                for(j=0; j<8; j++){
                        TM1618_CLK = 0;
                        delay_us(3);
                       
                        temp = GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_5);
                        usart_send_char(USART1,"PB5:%d        ",temp );
                       
                        if((i== 0) && (j == 1)){
                                status = temp;
                        }
                        TM1618_CLK = 1;
                        delay_us(3);
                }
                delay_us(6);
        }
        TM1618_STB = 1;
        delay_us(2);
        // 改回推挽输出
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;        // 通用推挽输出
        GPIO_Init(GPIOB, &GPIO_InitStructure);
        TM1618_DIO = 1;
        return status;
}
/*****************************************************
* name:        tm1618_DisPlay
* param:
* return:
* desc:        写显示寄存器,开启显示;四位八段
**************************************************/
void tm1618_DisPlay(void){
        u8 byte = 0x00;        // 显示模式,四位八段
        TM1618_STB = 0;       
        tm1618_WrByte( byte );       
        TM1618_STB = 1;
        delay_us(3);
}
/*****************************************************
* name:        dataConvert
* param:
* return:数字的数码管寄存器值
* desc:        将数字转化为数码管显示的寄存器值
**************************************************/
DisData_Structre dataConvert(u8 data){
        DisData_Structre disData;
        switch( data ){
                case 0:
                        disData.byte0 = 0x1f;
                        disData.byte1 = 0x08;
                        break;
                case 1:
                        disData.byte0 = 0x06;
                        disData.byte1 = 0x00;
                        break;
                case 2:
                        disData.byte0 = 0x1b;
                        disData.byte1 = 0x10;
                        break;
                case 3:
                        disData.byte0 = 0x0f;
                        disData.byte1 = 0x10;
                        break;
                case 4:
                        disData.byte0 = 0x06;
                        disData.byte1 = 0x18;
                        break;
                case 5:
                        disData.byte0 = 0x0d;
                        disData.byte1 = 0x18;
                        break;
                case 6:
                        disData.byte0 = 0x1d;
                        disData.byte1 = 0x18;
                        break;
                case 7:
                        disData.byte0 = 0x07;
                        disData.byte1 = 0x00;
                        break;
                case 8:
                        disData.byte0 = 0x1f;
                        disData.byte1 = 0x18;
                        break;
                case 9:
                        disData.byte0 = 0x0f;
                        disData.byte1 = 0x18;
                        break;
        }
        return disData;
}
/*****************************************************
* name:        tm1618_DisData
* param:要显示数据数组的头地址
* return:
* desc:        写显示寄存器,开启显示;四位八段
**************************************************/
void tm1618_DisData(u8* data){
        u8 i;
        u8 byte;
        DisData_Structre disData;
       
        byte = 0xc0;        // 显示地址从0xc0开始
        TM1618_STB = 0;
        tm1618_WrByte( byte );       
        for(i=0; i<4; i++){
                disData = dataConvert(data);
                if( i == 1){        // 显示小数点
                        disData.byte1 = disData.byte1 | 0x20;       
                }
                tm1618_WrByte( disData.byte0 );       
                tm1618_WrByte( disData.byte1 );       
        }               
        TM1618_STB = 1;
        delay_us(3);
       
        byte = 0x8f;        // 显示开关开,辉度为最亮14/16
        TM1618_STB = 0;
        tm1618_WrByte( byte );       
        TM1618_STB = 1;
        delay_us(3);
}
以下为串口1的输出,复位以后,从始至终没有按过按键
QQ截图20170328112951.png



友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。