|
本帖最后由 3205440665 于 2020-3-5 22:45 編輯
/*
截止2020.3.5,用protues8.8能正常仿真tm1637進行數碼管顯示,但是不能正常仿真按鍵檢測,
經與keil4聯調后發現,在仿真時DIO端口一直為0,哪怕寫上DIO=1;但是實際DIO依然為0;
導致按鍵檢測的返回值為0x00;目前還不能找到原因,
根據tm1638使用經驗,大概率是protues軟件問題,個人分析。
示例程序由官方程序修改,電路也按照官方要求連線。
*/
單片機源程序如下:
#include <reg52.h> //頭文件
#include "intrins.h" //包含_nop_()指令頭文件
#define nop _nop_();_nop_();_nop_();_nop_();_nop_(); //宏定義
/********************定義控制端口**********************/
sbit CLK=P1^0; //定義CLK
sbit DIO=P1^1; //定義DIO
/********************定義數據*************************/
unsigned char code CODE[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8, 0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e}; //共陽顯示數據0-F
/* 0 1 2 3 4 5 6 7 8 9 a b c d e f*/
unsigned char code TAB[10]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,};//數碼管不顯示
/********************延時函數,延時nms******************/
void delay_nms(unsigned int n)
{
unsigned int i;
while(n--)
for(i=0;i<550;i++);
}
/********************Start函數*************************/
void I2CStart()
{
DIO=1;
CLK=1;
nop;
DIO=1;
nop;
DIO=0;
nop;
CLK=0;
}
/********************Stop函數*************************/
void I2CStop()
{
CLK=0;
nop;
nop;
DIO=0;
nop;
nop;
CLK=1;
nop;
nop;
nop;
DIO=1;
nop;
CLK=0;
DIO=0;
}
/***************發送8bit數據,從低位開始**************/
void I2CWritebyte(unsigned char oneByte)
{
unsigned char i;
for(i=0;i<8;i++)
{
CLK=0;
if(oneByte&0x01)
DIO=1;
else
DIO=0;
nop;
CLK=1;
oneByte=oneByte>>1;
}
//8位數據傳送完
CLK = 0; //判斷芯片發過來的ACK應答信號
nop;
while(DIO==1);
nop;
CLK = 1;
nop;
}
/***************讀按鍵程序**************/
unsigned char read_key()
{
unsigned char rekey=0,i;
I2CStart();
I2CWritebyte(0x42); //寫讀鍵指令0x42
DIO=1;
for(i=0;i<8;i++)
{
CLK=0;
nop;
nop;
rekey=rekey>>1; //先讀低位
nop;
nop;
CLK=1;
if(DIO)
rekey=rekey|0x80;
else
rekey=rekey|0x00;
nop;
}
CLK = 0; //判斷芯片發過來的ACK應答信號
nop;
nop;
while(DIO==1);
nop;
nop;
CLK = 1;
nop;
nop;
I2CStop();
return rekey;
}
/************顯示函數,地址自加一************/
void disp0(unsigned char *p)
{
unsigned char i;
I2CStart();
I2CWritebyte(0x40); //數據命令設置:地址自動加1,寫數據到顯示寄存器
I2CStop();
I2CStart();
I2CWritebyte(0xc0); //地址命令設置:初始地址為00H
for(i=0;i<6;i++) //發送6字節數據到顯存
{
I2CWritebyte(*p);
p++;
}
I2CStop();
I2CStart();
I2CWritebyte(0x8C); //顯示控制命令:開顯示,脈沖寬度為11/16.
I2CStop();
}
/************顯示函數,固定地址寫數據************/
void smg_disp(unsigned char add, unsigned char value)
{
I2CStart();
I2CWritebyte(0x44); //數據命令設置:固定地址,寫數據到顯示寄存器
I2CStop();
I2CStart();
I2CWritebyte(0XC0+add); //地址命令設置:寫入add對應地址
I2CWritebyte(~CODE[value]); //給add地址寫數據
I2CStop();
I2CStart();
I2CWritebyte(0x8C); //顯示控制命令:開顯示,脈沖寬度為11/16.
I2CStop();
}
/************按鍵處理函數,按鍵數據低位在前高位在后************/
void key_process()
{
unsigned char temp;
temp=read_key(); //讀取按鍵返回值
P0=temp; //用于直觀顯示rekey的值
if(temp!=0xff)
{
disp0(TAB); //清屏
switch(temp)
{
case 0xf7 : smg_disp(0,1);break; //K1與SG1對應按鍵按下,顯示1
case 0xf6 : smg_disp(1,2);break; //K1與SG2對應按鍵按下,顯示2
case 0xf5 : smg_disp(2,3);break; //K1與SG3對應按鍵按下,顯示3
case 0xf4 : smg_disp(3,4);break; //K1與SG4對應按鍵按下,顯示4
case 0xef : smg_disp(4,5);break; //K2與SG1對應按鍵按下,顯示5
case 0xee : smg_disp(5,6);break; //K2與SG2對應按鍵按下,顯示6
}
}
}
void main()
{
smg_disp(0,6);
smg_disp(1,5);
smg_disp(2,4);
smg_disp(3,3);
smg_disp(4,2);
smg_disp(5,1);
delay_nms(1);
while(1)
{
key_process(); //問題:按鍵程序無用
delay_nms(100);
}
}
|
|