本人用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的输出,复位以后,从始至终没有按过按键
/*****************************************************************************
*版权信息:深圳天微电子有限公司
*文 件 名:TM1618-V1.0
*当前版本:V1.0
*MCU 型号:STC12C5608AD
*开发环境:Keil uVision4
*晶震频率:11.0592MHZ
*完成日期:2013-07-18
*程序功能:1.数码管驱动:驱动7段5位LED共阴数码管显示0~4;
2.按键功能 : 包含按键读程序驱动函数
*免责声明:1.此程序为TM1618驱动LED数码管演示程序,仅作参考之用。
2.如有直接使用本例程程序造成经济损失的,本公司不承担任何责任
********************************************************************************/
#include <reg52.h> //MCU头文件
#include "intrins.h" //包含nop指令头文件
#define uchar unsigned char //数据类型宏定义
#define uint unsigned int //数据类型宏定义
#define nop _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();//宏定义
/********************定义控制端口**********************/
sbit DIO=P1^0; //定义TM1618 DIO为P1^0;
sbit CLK=P1^1; //定义TM1618 CLK为P1^1;
sbit STB=P1^2; //定义TM1618 STB为P1^2;
/********************定义数据*************************/
//******************** 0 1 2 3 4
uchar code CODE_L[5]={0x1F,0x06,0x1B,0x0F,0x06,}; //共阴数码管0~5字型码
uchar code CODE_H[5]={0x08,0x00,0x10,0x10,0x18,};
uchar code CODE_L_OFF[6]={0x00,0x00,0x00,0x00,0x00,}; //共阴数码管不显示
uchar code CODE_H_OFF[6]={0x00,0x00,0x00,0x00,0x00,};
uchar KEY[3]={0}; //为存储按键值定义的数组
/***************延时函数nms**************/
void delay_nms(uint n)
{
uint i;
while(n--)
{
for(i=0;i<550;i++);
}
}
/***************发送8bit数据,从低位开始**************/
void send_8bit(uchar dat) //发送8位数据,从低位开始
{
uchar i;
for(i=0;i<8;i++)
{
CLK=0;
if(dat&0x01)
DIO=1;
else
DIO=0;
_nop_();
_nop_();
_nop_();
CLK=1;
dat>>=1;
}
CLK=0;
DIO=0;
}
/******************发送控制命令***********************/
void send_command(uchar com) //发送命令字节
{
STB=1; //STB置高
nop;
STB=0; //STB置低
send_8bit(com); //发送8bit数据
}
/****************读取按键值并存储*******************/
void read_key(void) //读取3字节按键值并存入数组KEY[],从低字节、低位开始
{
unsigned char i,j;
//DIO 输出
send_command(0x42); //发送读按键命令
DIO=1; //释放DIO数据总线
//DIO 输入
for(j=0;j<3;j++) //连续读取3个字节
{
for(i=0;i<8;i++)
{
CLK=0;
KEY[j]=KEY[j]>>1;
CLK=1;
if(DIO==1)
{
KEY[j]=KEY[j]|0x80;
}
nop;
} //0x00
nop;
nop;
}
CLK=0;
DIO=0;
STB=1;
}
/************显示函数,数码管1~7位显示0~6************/
void display(uchar *p1,uchar *p2) //显示函数,1~5位数码管显示0~4
{
uchar i;
send_command(0x01); //设置显示模式,5位7段模式
send_command(0x40); //设置数据命令,采用地址自动加1模式
send_command(0xc0); //设置显示地址,从00H开始
for(i=0;i<5;i++)
{
send_8bit(*p1); //从00H开始,向地址送显示数据
send_8bit(*p2);
p1++;
p2++;
}
send_command(0x8F); //设置显示命令,打开显示并设置占空比14/16.
STB=1;
}
/*****************按键处理函数*********************/
void key_process() // 按键处理函数
{
if(KEY[0]!=0x00)
{
if((KEY[0]==0x02)) {display(CODE_L,CODE_H);} //K2与KS1按键按下,数码管显示数字0~4
if((KEY[0]==0x10)) {display(CODE_L_OFF,CODE_H_OFF);} //K2与KS2按键按下,数码管显示关闭
}
}
void main()
{
display(CODE_L,CODE_H); //上电显示0~4
delay_nms(1);
while(1)
{
read_key(); //读按键值
key_process(); //按键处理
delay_nms(200); //延时200ms再读按键
}
}
一周热门 更多>