Ⅰ 通过键盘往单片机中输入任意数字的C语言程序
我这有个AVR的矩阵键盘的识别程序、其中PORTA就相当于51里的P0一样的端口的表示、PINA也是指的PORTA口、和PORTA的区别是PINA只能读!其他都一样的和51
/********************************************************
实验七: 矩阵式键盘实验
说明: 按按键K1-K16 数码管显示0-F的键码
注意: K17-K19为独立按键,使用这个程序是没有反应的
CPU型号: ATMEGA128A
晶振频率: 8MHZ
日期: 2011-3-12
联系方法: [email protected]
********************************************************/
#include <iom128v.h>
#include <macros.h>
#define uchar unsigned char
#define uint unsigned int
void Delayus(uint US); //微秒延时子程序
void Delayms(uint MS); //毫秒延时子程序
uchar key_scan(void);
void init_io(void);
//共阳数码管数字码
uchar led_discode[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xff};
uchar key_val=0;
//主函数
void main (viod)
{
uchar key_io;
init_io();
while(1)
{
PORTD=0XF0;
Delayms(5);
key_io=PIND & 0xf0;
if(key_io !=0xf0)
{
PORTD=0XF0;
Delayms(1);
key_io=PIND & 0xf0;
if(key_io !=0xf0)
{
key_val=key_scan();
key_val |= key_io;
}
switch(key_val)
{
case 0xee: key_val=0x00; break; //按键K1
case 0xde: key_val=0x01; break; //按键K2
case 0xbe: key_val=0x02; break; //按键K3
case 0x7e: key_val=0x03; break; //按键K4
case 0xed: key_val=0x04; break; //按键K5
case 0xdd: key_val=0x05; break; //按键K6
case 0xbd: key_val=0x06; break; //按键K7
case 0x7d: key_val=0x07; break; //按键K8
case 0xeb: key_val=0x08; break; //按键K9
case 0xdb: key_val=0x09; break; //按键K10
case 0xbb: key_val=0x0a; break; //按键K11
case 0x7b: key_val=0x0b; break; //按键K12
case 0xe7: key_val=0x0c; break; //按键K13
case 0xd7: key_val=0x0d; break; //按键K14
case 0xb7: key_val=0x0e; break; //按键K15
case 0x77: key_val=0x0f; break; //按键K16
} // switch(key_val)
} // if(key_io !=0xf0)
PORTD=0XF0;
//等待松开按键
key_io=PIND & 0xf0;
while(key_io !=0xf0)
{
key_io=PIND & 0xf0;
}
PORTC=led_discode[key_val]; //显示按键码
} // while(1)
}
void init_io(void)
{
DDRA=0XFF;//设置A口味输出
PORTA=0XFF;
DDRB=0XFf;;//设置B口味输出
PORTB=0XFF; //数码管位控制
DDRC=0XFF; //数码管段控制
PORTC=0X00;
DDRD=0X0F; //键盘接口
PORTD=0XF0;
DDRF=0X0E;
PORTF=0X0E;
PORTF&=0XF7; //锁存关闭LED显示
DDRB |=0X10; //PB4设为输出
PORTB|=0X10; //关闭PB4外接的LED
}
uchar key_scan(void)
{
uchar m,temp=0xf7;
for(m=0;m<4;m++)
{
PORTD=temp | 0xf0;
Delayms(1);
if((PIND & 0XF0)!=0XF0)
return(temp & 0x0f);
temp>>=1;
}
}
/****************************************************
函数名称: Delayus
功 能: 延时指定微秒(8M晶振)
参 数: US--延时的微秒数(大约,不是很精确,MS越大越准确)
返回值 : 无
/****************************************************/
void Delayus(uint US)
{
uint i;
US=US*5/4;
for( i=0;i<US;i++);
}
/****************************************************
函数名称: Delayms
功 能: 延时指定毫秒(8M晶振)
参 数: MS--延时的毫秒数
返回值 : 无
通过软件仿真反复实验得到的数值
/****************************************************/
void Delayms(uint MS)
{
uint i,j;
for( i=0;i<MS;i++)
for(j=0;j<1141;j++);
}
Ⅱ 求大神帮忙在这段单片机代码加一下注释
先说下,你的程序格式写的太占用空间了,而且看着也不够整洁
已经帮你都注释了,格式也做了调整,部分没有调整,方便添加注释
/***************************************************************************/
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit P26=P2^6; sbit P27=P2^7;//数码管片选控制用端口定义
sbit P20 =P2^0; sbit P21 =P2^1; sbit P22 =P2^2;//按键端口定义
uchar tt,a,b,c,d,e,f,second,minite, hour;//定义时分秒变量
uchar code smg[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};//数码管控制位
uchar code shuzi[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90, 0xbf};//数字0-9
void display(uchar a,uchar b,uchar c,uchar d ,uchar e,uchar f);//数码管显示函数定义
void delay(uint z);//延时函数定义
/***************************************************************************/
void keyscan()
{
TR1=0;//关闭定时器
P2 |=0x07;//初始化 P2 端口状态
if(P20==0)//如果按键被按下
{
delay(10);//延时去抖动
{
if(P20==0)//再次判断按键是否被按下
{
hour++;//小时 加一
if(hour==24){hour=0;}//如果达到24小时,则从0在开始
while(P20==0);//等待该按键松开
}
}
}//以下类推
if(P21==0){delay(10);if(P21==0){minite++;if(minite==60)minite=0;while(P21==0);}}
if(P22==0){delay(10);if(P22==0){second++;if(second==60)second=0;while(P22==0);}}
TR1=1;//打开定时器
}
/***************************************************************************/
void main()
{
hour=12; //初始化小时 变量
TMOD=0x10; //设置定时器1和计数器0
TH1=(65536-50000)/256; //定时器装初值,高四位
TL1=(65536-50000)%256; //定时器装初值,低四位
TR1=1; //启动定时器1
ET1=1; //启动定时器1中断
EA=1; //开总中断
P2 |=0x07; //初始化 P2 端口状态
while(1) //主循环
{
keyscan(); //调用按键处理函数
if(tt==60){tt=0;second++;} //如果达到60毫,秒加一
if(second==60){second=0;minite++;} //如果达到60秒,分加一
if(minite==60){minite=0;hour++;} //如果达到60分,小时加一
if(hour==24){hour=0;} //如果达到24小时,则从0在开始
f=second%10; e=second/10; //分离秒个位与十位的数值
d=minite%10; c=minite/10; //分离分个位与十位的数值
b=hour%10; a=hour/10; //分离小时个位与十位的数值
}
}
/***************************************************************************/
void display(uchar a,uchar b,uchar c,uchar d ,uchar e,uchar f)//数码管显示函数
{
P27=1; P1=smg[7]; P27=0; P26=1; P1=shuzi[f]; P26=0; P1=0; delay(1);//秒个位
P27=1; P1=smg[6]; P27=0; P26=1; P1=shuzi[e]; P26=0; P1=0; delay(1);//秒十位
P27=1; P1=smg[5]; P27=0; P26=1; P1=0xbf; P26=0; P1=0; delay(1);//分隔符
P27=1; P1=smg[4]; P27=0; P26=1; P1=shuzi[d]; P26=0; P1=0; delay(1);//分个位
P27=1; P1=smg[3]; P27=0; P26=1; P1=shuzi[c]; P26=0; P1=0; delay(1);//分十位
P27=1; P1=smg[2]; P27=0; P26=1; P1=0xbf; P26=0; P1=0; delay(1);//分隔符
P27=1; P1=smg[1]; P27=0; P26=1; P1=shuzi[b]; P26=0; P1=0; delay(1);//时个位
P27=1; P1=smg[0]; P27=0; P26=1; P1=shuzi[a]; P26=0; P1=0; delay(1);//时十位
}
/***************************************************************************/
void timer1() interrupt 3 //定时器中断函数
{
TH1=(65536-10000)/256; TL1=(65536-10000)%256;//重装定时器初值
tt++; display(a,b,c,d,e,f);//计数器 tt 累加,以及调用数码管显示函数
}
/***************************************************************************/
void delay(uint z) //延时函数
{uint t1,y; for(t1=z;t1>0;t1--){for(y=125;y>0;y--);}}//标准的 for 嵌套循环
/***************************************************************************/
Ⅲ 51单片机编写lcd1602显示程序,第一行显示自己的姓名,第二行显示学号
1、首先我们打开Keil μVision编译器,新建一个工程,然后保存在硬盘上的位置,然后选择Atmel-AT89C51单片机为模型,并启动器添加STARTUP.A51文件,然后在当前目录下新建一个C文件,并将其添加入工作路径。
Ⅳ C语言单片机编程。详解下面两段代码,解释区别,以及后面的代码载入后问题原因。
wela和la在两段代码里,都有类似的不同:先0后P0赋值再1,或者是先1后P0赋值再0,这样的差别对应的就是输出波形的时序不同。如果碰到对时序要求高的,会导致异常结果。
Ⅳ 单片机的加法指令中ADD与ADDS的区别
ADD不带进位加法指令;
指令名称:寄存器加法指令
指令代码:28H~2FH
指令功能:累加器内容与寄存器内容相加 操作内容:A←(A)+(Rn), n=0~7 字节数: 1
机器周期:1
影响标志位:C,AC,OV
ADDS是32位数的加法运算,影响进位标志位C而不影响运算结果的值,ADCS是大于32位数的加法,低32位数相加的结果影响标志位C的值(作为进位值)就得加到高32位数的相加运算里去,以此类推,可做高32数的加法。
例: 加两个 128 位的数
128 位结果:寄存器 0,1,2, 3
第一个 128 位数: 寄存器 4,5,6,7
第二个 128 位数: 寄存器 8,9,10,11
ADDS R0, R4, R8 ; 加低端的字,影响C
ADCS R1, R5, R9 ; 加下一个字, +C
ADCS R2, R6, R10 ; 加第三个字, +C
ADCS R3, R7, R11 ; 加高端的字, +C
Ⅵ 单片机C51编程(C语言):实现学号的显示(学号是10位数字)
你用什么驱动数码管呢?
不同的驱动,程序写法不同。
如果直接用I/O口驱动,8位数码管就这样写:
wei=位选
an=段选
//断码表
uchar
code
shuzi[12]={0xc0,0xf9,0xa4,0xb0,0x99,//0,1,2,3,4,
0x92,0x82,0xf8,0x80,0x90,//5,6,7,8,9,
0x00,0xff};
void
led_scan(void)
{
uchar
i,j;//共阳数码管
wei=0xff;
j=0x01;
for(i=0;i<8;i++)
{
an=shuzi[i];
wei=!j;
delay(200);
j<<=1
;
}
wei=0xff;
}
Ⅶ 关于单片机数码管的C语言代码,高分求详解,先谢过
一、LedNumVal%10000/1000 %是模,取余数的意思,%10000,得到的数最大是四位数。 /是整除的意思不带小数,如8/3=2 一个小于10000的数,整除1000结果一定是0到9之间的一个数
二、Disp_Tab 以及LedOut, dispbit都是数组,根据相应的数可得到对应的字符数据,达到位选的功能。
Ⅷ 单片机加法类指令
CLR
A
并不清理进位
带进位与0相加时,就把进位(只可能是0或1)放进A
中
了
然后再传送出去
53单元也只能是0或1
Ⅸ 求单片机 数字钟 c语言代码注释
#include<reg51.h>
unsigned char code su[11]={0x3f,0x06,0x5b,0X4F,0x66,0X6D,0x7d,0x07,0x7f,0x6f,0x40};//数码管显示
unsigned char xian[8]={0,0,10,0,0,10,0,0};
unsigned char sen=0,min=0,hou=0,sen2=0,min2=0,hou2=0,sen3=59,min3=59,hou3=23,num;//变量定义
//--------引脚定义
sbit ks=P1^4; //秒按键
sbit km=P1^5; //分按键
sbit kh=P1^6; //时按键
sbit ds=P1^7;
sbit bb=P3^4;
//-------8个数码管位显示接口
sbit P20=P2^0;
sbit P21=P2^1;
sbit P22=P2^2;
sbit P23=P2^3;
sbit P24=P2^4;
sbit P25=P2^5;
sbit P26=P2^6;
sbit P27=P2^7;
bit jp1,jp2,jp3;//位定义
int n=0,jp4;
//----演示程序
void daly()
{
unsigned char j;
for(j=60;j;j--);//for循环
}
//------数码管显示
void show()
{
xian[0]=hou/10; //时的十位
xian[1]=hou%10; //时的个位
xian[3]=min/10; //分的十位
xian[4]=min%10; //分的个位
xian[6]=sen/10; //秒的十位
xian[7]=sen%10; //秒的个位
P0=su[xian[7]]; //八段数码管显示秒的个位
P20=0; //动态显示,打开第一个数码管
daly(); //延时
P20=1; //动态显示,关闭第一个数码管
P0=su[xian[6]];//八段数码管显示秒的十位
P21=0;//动态显示,打开第二个数码管
daly();//延时
P21=1;//动态显示,打开第二个数码管
//--------------------
P0=su[xian[5]];//注:你xian[3]xian[5]都为从定义
P22=0;
daly();
P22=1;
//-------------分个位的显示
P0=su[xian[4]];
P23=0;
daly();
P23=1;
//-----------
P0=su[xian[3]];//注:你xian[3]xian[5]都为从定义
P24=0;
daly();
P24=1;
//------------分十位的显示
P0=su[xian[2]];
P25=0;
daly();
P25=1;
//-------------时个位的显示
P0=su[xian[1]];
P26=0;
daly();
P26=1;
//-----------时十位的显示
P0=su[xian[0]];
P27=0;
daly();
P27=1;
}
//---------按键程序
void key()
{
if((ks==0)&&(jp1==0))
{
jp1=1;//秒按键生效
daly();//消抖
if(ks==0) sen++; //秒加1
}
else if((ks==1)&&(jp1==1)) jp1=0;//秒按键未生效
if(sen==60)//等于60时
{
min++;//分加1
sen=0;//秒清零
}
if((km==0)&&(jp2==0))
{
jp2=1;//分按键生效
daly();//消抖
if(km==0) min++;//分加1
}
else if((km==1)&&(jp2==1)) jp2=0;//分按键未生效
if(min==60)//等于60时
{
hou++;//时加1
min=0;//分清零
}
if((kh==0)&&(jp3==0))
{
jp3=1;//时按键生效
daly(); //消抖
if(kh==0) hou++;//时加1
}
else if((kh==1)&&(jp3==1)) jp3=0;//时按键未生效
if(hou==24) hou=0;//时为24时,清零
if(ds==0)//定时操作
{
daly();//消抖
while(ds==0);
daly();
if(ds==1) jp4++;//定时按键生效,加一
if(jp4>1) jp4=0;//JP4只能是一。
/*注:就本人感觉而言这两句就是废话,一句就能完事:if(ds==1) jp4=1;*/
}
}
//-------从功能上看这是定时
dings()
{
EA=0; //关闭中断
TR0=0;//T0停止计数
hou2=hou;//把现有的时分秒,保留储存在hou2,min2,sen2
min2=min;
sen2=sen;
hou=0; //清零
min=0;
sen=0;
while(jp4==1) //等待直到按键生效
{
hou3=hou; //把现有的时分秒,保留储存在hou3,min3,sen3
min3=min;
sen3=sen;
show(); //现实
key();//按键扫描
hou3=hou;//把按键后更改的时分秒,也就是定时时间,保留储存在hou3,min3,sen3
min3=min;
sen3=sen;
}
hou=hou2;//把远有的时间分别还原
min=min2;
sen=sen2;
EA=1;//开中断
TR0=1;//T0计数
}
void main()
{
TMOD=0x01;//定时器0方式1
TH0=45535>>8;//赋初值
TL0=45535;
EA=1; //允许中断
ET0=1;//T0中断使能
EX1=1;//外部中断1
TR0=1;//T0开始计数
hou3=99;
min3=99;
sen3=99;
while(1)
{
show();//显示
key();//按键程序
dings();//定时操作
if(((hou*60+min))*60+sen>=((hou3*60+min3))*60+sen3 )//判断是否到了定时时间
{
bb=0;//蜂鸣器鸣叫(也可能是其他音乐芯片)
num++;
if(num>=500) //鸣叫延时
{
bb=1; //蜂鸣器关闭
num=0; //延时计数清零
jp4=0;//位清零
hou3=99;//重新赋值
min3=99;
sen3=99;
}
}
}
}
void_time0_(void)interrupt 1
{
TL0=45535; //定时器0重新赋值
TH0=45535>>8;
if(++n==50) //1秒
{
n=0;
sen++; //秒加1
if(sen==60) //加到60
{
min++;
sen=0;
}//分加1
if(min==60)//加到60
{
hou++;
min=0;
}//时加1
if(hou==24) hou=0;//24时,时变成0
}
}
说实话,这个程序编写的很烂。