这也收费,太缺德了。哥给你!
uchar keyval()
{
uchar a,b,i;
b=0xfe;
for(i=0;i<4;i++) //i为行号
{
KEY=b;a=KEY;
if((a&0x10)==0) keynum=i4; //第一列
if((a&0x20)==0) keynum=i4+1; //第二列
if((a&0x40)==0) keynum=i4+2; //第三列
if((a&0x80)==0) keynum=i4+3; //第四列
b<<=1;b++;
}
SpeakContinue(1);
return (keynum);
}
/延时/
void delay(uchar t)
{
uchar i=100;
while(t--)
{while(i--);}
}
void delay1(uchar time)
{
while(time--);
}
/LCD驱动/
//写控制字函数
void lcdcmd(uchar cmd)
{
RS=0;
RW=0;
DAT=cmd;
E=1;
_Nop();
_Nop();
E=0;
delay(2);
}
//写数据函数
void lcddata(uchar dat)
{ RS=1;
RW=0;
DAT=dat;
_Nop();
E=1;
_Nop();
_Nop();
E=0;
delay(2);
}
//LCD初始化函数
void lcdinit() //显示初始化
{
lcdcmd(0x38);
delay(2);
lcdcmd(0x38);
delay(2);
lcdcmd(0x38);
delay(2);
lcdcmd(0x01);
lcdcmd(0x06);
lcdcmd(0x0c);
}
记得给分
给你写一个吧,累死了,要采纳哦:
#include<reg51h>
#define uchar unsigned char
#define uint unsigned int
uchar code table0[]="Tempeture:";
uchar code table1[]="welcom to text!";
sbit lcdrs=P3^5;
//sbit lcdrw=P2^1;
sbit lcden=P3^4;
sbit ds=P2^2;
sbit beep=P2^3;
sbit dula=P2^6;
sbit wela=P2^7;
bit flag;
uchar num;
uint temp,t;
uchar temp_bai,temp_shi,temp_ge,temp_little;
float xs_temp;
void delay(uint z)//延时1ms子程序
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void ds_reset( ) //DS18B20初始化
{
uint i;
bit pw=1;
while(pw)
{
ds=1;
i++;
ds=0;
i=103;
while(i>0)i--;//835us
ds=1;
i=4;
while(i>0)i--;//35us
pw=ds;
}
i=70;
while(i>0)i--;//604us
ds=1;
}
void temp_wr_byte(uchar dat)//DS18B20写一个字节的数据子程序
{
bit testb;
uchar j;
uint i;
for(j=0;j<8;j++)
{
testb=dat&0x01;
dat=dat>>1;
if(testb) //textb为真写1,
{
ds=0; //i++;i++;
i=1;
while(i>0)i--; //至少1us
ds=1;
i=8;
while(i>0)i-- ; //66us
}
else
{
ds=0; //写0
i=8;
while(i>0)i--;
ds=1; //对IO线进行写0
i=1;
while(i>0)i--;
}
}
}
bit temp_rd_bit( ) //读一位数据子程序
{
uint i;
bit dat;
ds=1;
i=0;
ds=0; //2us
i++;
i++;
ds=1; //6us
i++; //3us
dat=ds;
i=4;
while(i>0)i--; //32us
return(dat);
}
uchar tempread( )//读一个字节数据
{
uchar i,j,dat;
dat=0;
for(i=0;i<8;i++)
{
j=temp_rd_bit( );
dat=(j<<7)|(dat>>1); //读出数据最低位在最前面,刚好一个字节在dat里
}
return(dat); //读了8次即8个字节
}
void tempchange( ) //启动温度转换
{
ds_reset( );
// delay(1);
temp_wr_byte(0xcc); //跳过ROM
temp_wr_byte(0x44); //启动温度转换
}
void temp_rec( ) //读取温度数据
{
uchar a,b;
ds_reset( );
// delay(1);
temp_wr_byte(0xcc);
temp_wr_byte(0xbe); //从暂存寄存器读字节
a=tempread( );
b=tempread( );
temp=b;
temp<<=8; //保留最高位
temp=temp|a;
if(temp<0x7fff)//是否为正数?
{
flag=0;
}
else
{
flag=1; //为负数时,温度数据要反向
temp=~temp+1;
}
xs_temp=temp00625; //分辨率为1/2^12
}
void write_com(uchar com)//液晶写指令 *** 作子程序
{
lcdrs=0;
P0=com;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
void write_date(uchar date)//液晶写数据 *** 作子程序
{
lcdrs=1;
P0=date;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
void lcd_init( )//液晶初始化子程序
{
dula=0;
wela=0;
lcden=0;//lcdrw=0;
write_com(0x38); //基本指令集
write_com(0x0c); //整体显示开,游标和游标位置关
write_com(0x06); //写一个字节时,地址指针加1,光标加1
write_com(0x01); // 清DDRAM
// write_com(0x80); //将DDRAM地址到地址计数器AC,12864中用
while(table1[num]!='\0')
{write_date(table1[num]);
num++;
delay(50);
}
}
void shujucl( )//数据处理子函数
{
t=xs_temp10; //小数点后边只显示1位,
temp_bai=t/1000+0x30; //让其显示0x3x,对应着asc的数字
temp_shi=t%1000/100+0x30;
temp_ge=t%100/10+0x30;
temp_little=t%10+0x30;
if(xs_temp<12||xs_temp>15)
beep=0;
else beep=1;
}
void xianshi( )
{ write_com(0x80); //设定DDRAM地址
for(num=0;num<11;num++)
{
write_date(table0[num]);
delay(5);
}
write_com(0x80+0x40); //设置显示到对应的地址
if(flag==1)
write_date('-'); //表示温度为负数
else
write_date(temp_bai);
write_com(0x8a+0x40); //设定到0x8b所在位
write_date(temp_shi);
write_com(0x8b+0x40);
write_date(temp_ge);
write_com(0x8c+0x40);
write_date('');
write_com(0x8d+0x40); //设置到第二个字节
write_date(temp_little);
delay(5);
}
void main( )
{
lcd_init( );
ds_reset( ) ;
while(1)
{
tempchange( ); //启动温度转换
temp_rec( ); //读取温度数据
shujucl( ); //数据处理
xianshi( ); //数据显示
}
}
#include <intrinsh>
#define uchar unsigned char
#define ROWP P3
#define LINP P2
void Delay(uchar i) {
uchar j;
for(;i>0;i--)
for(j=0;j<112;j++)
_nop_();
}
uchar Keyscan(){
uchar i,j,RLP,num;
for(i=0;i<4;i++){
LINP=(LINP|0xf0)&(~(0x10<<i));
Delay(1);
for(j=0;j<5;j++){
RLP=(ROWP|0x1f)&(~(0x10>>j));
if(ROWP==RLP){
Delay(2);
if(ROWP==RLP)
num=i5+j+1;
}
}
}
return num;
}
54的,稍微修改,就是44的
这个你看看可以参考!
#include<reg51h>
#include<intrinsh>
#define uint unsigned int
#define uchar unsigned char
uchar code table[10] = {0x03, 0x9f, 0x25, 0x0d, 0x99, 0x49, 0x41, 0x1f, 0x01, 0x09};
//这三个引脚参考资料
sbit E=P2^7; //1602使能引脚
sbit RW=P2^6; //1602读写引脚
sbit RS=P2^5; //1602数据/命令选择引脚
/
名称 : Delay_1ms()
功能 : 延时子程序,延时时间为 1ms x
输入 : x (延时一毫秒的个数)
输出 : 无
/
void Delay_1ms(uint i)//1ms延时
{
uchar x,j;
for(j=0;j<i;j++)
for(x=0;x<=148;x++);
}
/
名称 : delay()
功能 : 延时,延时时间大概为5US。
输入 : 无
输出 : 无
/
void delay()
{
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}
/
名称 : bit Busy(void)
功能 : 这个是一个读状态函数,读出函数是否处在忙状态
输入 : 输入的命令值
输出 : 无
/
bit Busy(void)
{
bit busy_flag = 0;
RS = 0;
RW = 1;
E = 1;
delay();
busy_flag = (bit)(P0 & 0x80);
E = 0;
return busy_flag;
}
/
名称 : wcmd(uchar del)
功能 : 1602命令函数
输入 : 输入的命令值
输出 : 无
/
void wcmd(uchar del)
{
while(Busy());
RS = 0;
RW = 0;
E = 0;
delay();
P0 = del;
delay();
E = 1;
delay();
E = 0;
}
/
名称 : wdata(uchar del)
功能 : 1602写数据函数
输入 : 需要写入1602的数据
输出 : 无
/
void wdata(uchar del)
{
while(Busy());
RS = 1;
RW = 0;
E = 0;
delay();
P0 = del;
delay();
E = 1;
delay();
E = 0;
}
/
名称 : L1602_init()
功能 : 1602初始化,请参考1602的资料
输入 : 无
输出 : 无
/
void L1602_init(void)
{
wcmd(0x38);
wcmd(0x0c);
wcmd(0x06);
wcmd(0x01);
}
/
名称 : L1602_char(uchar hang,uchar lie,char sign)
功能 : 改变液晶中某位的值,如果要让第一行,第五个字符显示"b" ,调用该函数如下
L1602_char(1,5,'b')
输入 : 行,列,需要输入1602的数据
输出 : 无
/
void L1602_char(uchar hang,uchar lie,char sign)
{
uchar a;
if(hang == 1) a = 0x80;
if(hang == 2) a = 0xc0;
a = a + lie - 1;
wcmd(a);
wdata(sign);
}
/
名称 : L1602_string(uchar hang,uchar lie,uchar p)
功能 : 改变液晶中某位的值,如果要让第一行,第五个字符开始显示"ab cd ef" ,调用该函数如下
L1602_string(1,5,"ab cd ef;")
输入 : 行,列,需要输入1602的数据
输出 : 无
/
void L1602_string(uchar hang,uchar lie,uchar p)
{
uchar a,b=0;
if(hang == 1) a = 0x80;
if(hang == 2) a = 0xc0;
a = a + lie - 1;
while(1)
{
wcmd(a++);
b++;
if((p == '\0')||(b==16)) break;
wdata(p);
p++;
}
}
/
名称 : Keyscan()
功能 : 实现按键的读取。下面这个子程序是按处理 矩阵键盘 的基本方法处理的。
输入 : 无
输出 : 按键值
/
uchar Keyscan(void)
{
uchar i,j, temp, Buffer[4] = {0xfe, 0xfd, 0xfb, 0xf7};
for(j=0; j<4; j++)
{
P1 = Buffer[j];
temp = 0x10;
for(i=0; i<4; i++)
{
if(!(P1 & temp))
{
return (i+j4);
}
temp <<= 1;
}
}
}
/
名称 : Main()
功能 : 主函数
输入 : 无
输出 : 无
/
void Main(void)
{
uchar Key_Value; //读出的键值
L1602_init();
L1602_string(1,1," 44 KeyBoard ");
L1602_string(2,1,"You Press The ");
while(1)
{
P1 = 0xf0;
if(P1 != 0xf0)
{
Delay_1ms(20); //按键消抖
if(P1 != 0xf0)
{
Delay_1ms(20); //按键消抖
if(P1 != 0xf0)
{
Key_Value = Keyscan();
}
}
}
L1602_char(2,15,Key_Value / 10 + 48);
L1602_char(2,16,Key_Value % 10 + 48);
}
}
假设按下的是S1键进行如下检测(44键盘)
先在P3口输出
p3 00001111
低四位 行会有变化
cord_h =00001111&00001110 =00001110
if !=00001111
延时01us
cord_h=00001110&00001111=00001110
if !=00001111
P3再输出11111110
P3 =00001110|11110000=11111110
输出高四位
cord_l=P3&0xf0 //此时P3口就是输入值01111110 而不是上面的11111110
cord_l=01111110&11110000=01110000
cord_h+cord_l=00001110+01110000=01111110=0x7e //此编码即为S1的编码
#include <reg52h>//包含头文件
#define uchar unsigned char
#define uint unsigned int
unsigned char const table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,
0x77,0x7c,0x39,0x5e,0x79,0x71};//0-F
uchar keyscan(void);
void delay(uint i);
void main()
{
uchar key;
P2=0x00;//1数码管亮 按相应的按键,会显示按键上的字符
while(1)
{
key=keyscan();//调用键盘扫描,
switch(key)
{
case 0x7e:P0=table[0];break;//0 按下相应的键显示相对应的码值
case 0x7d:P0=table[1];break;//1
case 0x7b:P0=table[2];break;//2
case 0x77:P0=table[3];break;//3
case 0xbe:P0=table[4];break;//4
case 0xbd:P0=table[5];break;//5
case 0xbb:P0=table[6];break;//6
case 0xb7:P0=table[7];break;//7
case 0xde:P0=table[8];break;//8
case 0xdd:P0=table[9];break;//9
case 0xdb:P0=table[10];break;//a
case 0xd7:P0=table[11];break;//b
case 0xee:P0=table[12];break;//c
case 0xed:P0=table[13];break;//d
case 0xeb:P0=table[14];break;//e
case 0xe7:P0=table[15];break;//f
}
}
}
uchar keyscan(void)//键盘扫描函数,使用行列反转扫描法
{
uchar cord_h,cord_l;//行列值
P3=0x0f; //行线输出全为0
cord_h=P3&0x0f; //读入列线值
if(cord_h!=0x0f) //先检测有无按键按下
{
delay(100); //去抖
cord_h=P3&0x0f; //读入列线值
if(cord_h!=0x0f)
{
P3=cord_h|0xf0; //输出当前列线值
cord_l=P3&0xf0; //读入行线值
return(cord_h+cord_l);//键盘最后组合码值
}
}return(0xff); //返回该值
}
void delay(uint i)//延时函数
{
while(i--);
}
void delay() //延时子程序
{
unsigned char n, m;
for (n = 100; n > 0; n--)
for (m = 300; m > 0; m--);
}
unsigned char Keycan(void) //按键扫描程序 P10--P13为行线 P14--P17为列线
{
unsigned char rcode, ccode;
P1 = 0xF0; // 发全0行扫描码,列线输入
if((P1&0xF0) != 0xF0) // 若有键按下
{
delay();// 延时去抖动
if((P1&0xF0) != 0xF0)
{ rcode = 0xFE; // 逐行扫描初值
while((rcode&0x10) != 0)
{
P1 = rcode; // 输出行扫描码
if((P1&0xF0) != 0xF0) // 本行有键按下
{
ccode = (P1&0xF0)|0x0F;
do{;}while((P1&0xF0) != 0xF0); //等待键释放
return ((~rcode) + (~ccode)); // 返回键编码
}
else
rcode = (rcode<<1)|0x01; // 行扫描码左移一位
}
}
}
return 0; // 无键按下,返回值为0
}
这个。。流水灯用for()语句来循环,循环内部用delay来延时控制流水的运转速度。
设置一个变量M,这个变量在每次循环的情况下都要赋值一次,从哪里赋值呢??就是判断一下你指定按键是否按下,按下了,这个变量M为1,没按下,这个变量M为0,然后你在for语句的中间那个判断表达式中加入一个条件:那就是这个变量M是(M=1就满足条件,继续循环,M=0不满足,就跳出循环)。这样就实现了按键终止循环的行为
然后你在for循环外边也不断判断这个按键的状态,并随时给这个M变量更新值,这样,你跳出来循环之后就不会回不去,如此的话,你就按住不放就会暂停,放开就继续流水
但是你如果要求按一下就流水,再按一下就暂停,第三次按又流水,那你将按键按下计数,然后根据你按下按键次数进行对流水灯的 *** 作。。。。。
以上就是关于求 用单片机AT89S52 4*4矩阵键盘 LCD1602 实现计算器的功能的C程序 .原理图 硬件 我以做出来全部的内容,包括:求 用单片机AT89S52 4*4矩阵键盘 LCD1602 实现计算器的功能的C程序 .原理图 硬件 我以做出来、求一个C程序:(温度控制系统)用矩阵键盘中的三个键设定温度调节然后再用1602液晶显示、4*4矩阵键盘控制四位数码管显示单片机C语言程序等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)