#include <reg52h>
#include "delayh"
#include "lcd1602h"
sbit SCK = P2^0;//sbit定义单片机的特殊功能寄存器变量
sbit SDA = P2^1;
bit ack = 0;//bit定义变量
void iic_start()
{
SDA = 1;
SCK = 1;
delay_us(1);
SDA = 0;
delay_us(1);
SCK = 0;//钳住总线,等待下次使用
}
void icc_stop()
{
SDA = 0;
SCK = 1;
delay_us(1);
SDA = 1;
delay_us(1);
SCK = 0;//钳住总线,等待下次使用
}
void iic_send_byte(unsigned char byte)
{
unsigned char i;
for(i = 0;i<8;i++)
{
SDA = byte & 0x80;//非0为1
SCK = 1;
delay_us(1);
SCK = 0;
byte <<=1;//左移一位
}
SDA = 1;
SCK = 1;
delay_us(1);
if(0 == SDA)//有应答
ack = 0;
else //无应答
ack =1;
SCK = 0;//钳住总线,等待下次使用
}
unsigned char iic_rcv_byte()
{
unsigned char i,temp;
SDA = 1;
for(i = 0;i < 8;i ++)
{
SCK = 0;
delay_us(1);
SCK = 1;
delay_us(1);
temp <<= 1;
if(SDA)
temp = temp+ 1;
}
SCK = 0;
return temp;
}
void iic_ack()
{
SDA = 0;
SCK = 1;
delay_us(1);
SCK = 0;
}
void iic_noack()
{
SDA = 1;
SCK = 1;
delay_us(1);
SCK = 0;
}
void AT_send_str(unsigned char deviceaddr,unsigned char romaddr,unsigned char s,unsigned char num)
{
unsigned char i;
iic_start();
iic_send_byte(deviceaddr);
if(ack == 1)
return;
iic_send_byte(romaddr);
if(ack == 1)
return;
for(i = 0;i < num; i ++)
{
iic_send_byte(s);
if(ack == 1)
return;
s++;
}
icc_stop();
}
void AT_rcv_str(unsigned char deviceaddr,unsigned char romaddr,unsigned char s,unsigned char num )
{
unsigned char i;
//SDA = 1;
iic_start();
iic_send_byte(deviceaddr);
if(ack == 1)
return;
iic_send_byte(romaddr);
if(ack == 1)
return;
iic_start();
iic_send_byte(deviceaddr + 1);
if(ack == 1)
return;
for(i = 0;i < num - 1; i++)
{
s = iic_rcv_byte();
iic_ack();//
s++;
}
s = iic_rcv_byte();
iic_noack();
icc_stop();
}
void main()
{
unsigned char i;
unsigned char testbuf[20] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,16,16,17,18,19};
unsigned char rcvbuf[20];
lcd_init();
AT_send_str(0xae,0,testbuf,10);
delay_ms(200);
AT_rcv_str(0xae,0,rcvbuf,10);
for(i = 0;i < 10; i++)
{
display_lcd_char(i,0,rcvbuf[i]+0x30);
}
while(1);
}
先在KEIL中编译生成HEX文件
(如果编译完了目录内没有找到HEX文件,在项目设置里,C51项中,勾上生成HEX文件选择)
再用COM51来烧。
(这个参照软件说,较简单。一般先载入HEX文件再点个AUTO就可以了)
流水灯就是51单片机控制led灯依次点亮的控制方式。具体程序如下:
ORG 0000H ;复位启动
AJMP START ;
ORG 001BH ;T1中断
AJMP T1INT ;
;定义变量========================
YSJS EQU 30H;延时计数器
LED EQU 31H;LED控制缓冲器
;主程序==========================
START: MOV LED,#0FEH ;初始化数据
MOV YSJS,#0 ;
MOV TMOD,#10H ;定时器1工作于方式1,16位定时器
MOV TL1,#0B0H ;设置定时初值
MOV TH1,#3CH ;定时时间=50mS
SETB ET1 ;使能定时器1中断
SETB TR1 ;启动定时器1
SETB EA ;开总中断
MOV P1,LED ;初始化流水灯
LOOP: JMP LOOP ;循环等待中断
T1INT: PUSH PSW ;定时器1中断程序
PUSH ACC ;保护现场
MOV TH1,#3CH ;定时时间=50mS
MOV TL1,#0B0H ;
INC YSJS ;
PUSH ACC ;保护ACC
MOV A,YSJI ;
CJNE A,#2,QT1 ;50mS2=100mS
MOV P1,LED ;
MOV A,LED ;
RL A ;累加器A的值循环左移1位
MOV LED,A ;
MOV YSJS,#0 ;
QT1: POP ACC ;恢复现场
POP PSW ;
RETI ;返回主程序
END ;汇编程序结束
扩展资料:
实现流水灯的三个方法:
第一种,总线方法实现流水灯。这是一种比较笨但又最易理解的方法,采用顺序程序结构,用位指令控制P1口的每一个位输出高低电平,加上延时函数,即可控制每个LED灯的亮灭。
第二种,移位方法实现流水灯采用循环程序结构编程。首先在程序开始给P10口送一个低电平,其它位为高。然后延时一段时间再让低电平往高位移动,这样就实现“流水”的效果了。
第三种,库函数实现流水灯。利用左移函数进行。
#include <AT89X51H>
unsigned char code dispcode[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00}; //定义显示用的段码
unsigned char dispbitcode[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; //定义显示用的位码
unsigned char dispbuf[8]={0,0,16,0,0,16,0,0}; //定义显示缓冲区
unsigned char dispbitcnt; //定义显示的位
unsigned char second; //定义秒
unsigned char minite; //定义分钟
unsigned char hour;//定义小时
unsigned int tcnt;//定义定时累加器
unsigned char mstcnt;//定义毫秒累加器
unsigned char i,j;
void main(void) //主函数
{
TMOD=0x02; //设置定时器工作模式
TH0=0x06; //设置初值
TL0=0x06;
TR0=1; //开定时器
ET0=1; //开定时器中断
EA=1; //开总中断
while(1)
{
if(P0_0==0) //判断P00口的按键是否按下
{
for(i=5;i>0;i--)
for(j=248;j>0;j--);//延时消抖
if (P0_0==0) //判断按键真的按下了
{
second++; //秒加1
if(second==60) //秒加到60?
{
second=0; //秒清零
}
dispbuf[0]=second%10; //取秒的个位放在显示缓冲
dispbuf[1]=second/10; //取秒的十位放在显示缓冲
while(P0_0==0); //等待,知道按键松开
}
}
if(P0_1==0) //p01的按键按下,设置分钟,请参考秒的程序,一样的
{
for(i=5;i>0;i--)
for(j=248;j>0;j--);
if(P0_1==0)
{
minite++;
if(minite==60)
{
minite=0;
}
dispbuf[3]=minite%10;
dispbuf[4]=minite/10;
while(P0_1==0);
}
}
if(P0_2==0) //p02的按键按下,设置小时,请参考秒的程序,一样的
{
for(i=5;i>0;i--)
for(j=248;j>0;j--);
if(P0_2==0)
{
hour++;
if(hour==24)
{
hour=0;
}
dispbuf[6]=hour%10;
dispbuf[7]=hour/10;
while(P0_2==0);
}
}
}
}
void t0(void) interrupt 1 using 0 //定时器中断函数
{
mstcnt++; //累加器加一
if(mstcnt==8) //计时满8毫秒?
{
mstcnt=0; //累加器清零
P1=dispcode[dispbuf[dispbitcnt]]; //送显示段码
P3=dispbitcode[dispbitcnt]; //送显示位码
dispbitcnt++; //显示位加1
if(dispbitcnt==8) //8位都显示完了?
{
dispbitcnt=0; //从第一位开始显示
}
}
tcnt++; //累加器加一
if(tcnt==4000) //记满1秒
{
tcnt=0; //累加器清零
second++; //秒加一
if(second==60) //秒满60?
{
second=0; //秒清零
minite++; //分钟加一
if(minite==60) //分钟满60
{
minite=0; //分钟清零
hour++; //小时加1
if(hour==24) //小时满24
{
hour=0; //小时清零
}
}
}
dispbuf[0]=second%10; //将时分秒的个位与十位分开,装在显示区
dispbuf[1]=second/10;
dispbuf[3]=minite%10;
dispbuf[4]=minite/10;
dispbuf[6]=hour%10;
dispbuf[7]=hour/10;
}
}
其实这个程序不难,仔细想想,有不懂的再问我吧
以上就是关于用51单片机编写个小程序全部的内容,包括:用51单片机编写个小程序、用keil如何给51单片机烧写程序、51单片机中如何用汇编语言编写流水灯等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)