本人用STM32F103RCT6进行数码管的实验,试验中,数码管显示无问题(即MCU与1618的通讯没有问题),但是按键扫描一直不能成功。特开此帖请教!!!
以下是原理图
以下是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的输出,复位以后,从始至终没有按过按键
一周热门 更多>