我这是C语言版 我自己编的,测试通过 其易懂
#include<at89x52h>
#include<intrinsh>
#define uchar unsigned char
#define uint unsigned int
sbit beep=P1^7;
bit sd,ds,dscz;
uchar count,sheding,dingshi;
uchar bdata sdyw; //可位寻址存储器设定
sbit sdyw_0=sdyw^0;
sbit sdyw_1=sdyw^1;
sbit sdyw_2=sdyw^2;
sbit sdyw_3=sdyw^3;
sbit sdyw_4=sdyw^4;
sbit sdyw_5=sdyw^5;
uchar bdata dsyw; //可位寻址存储器设定
sbit dsyw_0=dsyw^0;
sbit dsyw_1=dsyw^1;
sbit dsyw_2=dsyw^2;
sbit dsyw_3=dsyw^3;
sbit dsyw_4=dsyw^4;
sbit dsyw_5=dsyw^5;
uchar dismiaoshi,dismiao,disfen,disfenshi,disshi,disshishi; // 时钟显示用
uchar dsmiao,dsmiaoshi,dsdisfen,dsdisfenshi,dsdisshi,dsdisshishi ; // 定时显示用
delay(uint);//延时子函数声明
sbit rs=P1^0; sbit lcden=P1^2; sbit rw=P1^1;//与1602接口引脚
uchar table1[]="0123456789";
writecom(uchar com) //写指令子函数
{
P0=com;
rs=0;
lcden=0;delay(10);
lcden=1;delay(10);
lcden=0;
}
writedate(uchar date) //写数据子函数
{
P0=date;rs=1;
lcden=0;delay(10);
lcden=1;delay(10);
lcden=0;
}
void init() //初始化
{
writecom(0x38);delay(20); //子函数前面先写出来,下面才能掉用
writecom(0x0c);delay(20);
writecom(0x06);delay(20);
}
void main()
{
rw=0;//写允许
P2_4=0;//键盘用
init(); // 这里不能要“void”
EA=1;ET1=1;TMOD=0x10;
TH1=(65536-46200)/256;
TL1=(65536-46200)%256;
TR1=1;
writecom(0x84);delay(10);writedate(':');//这里不能用双引号
writecom(0x87);delay(10);writedate(':');
while(1)
{
if(ds==0) //若进入定时程序,这里不显,去显定时值,但时分秒数据在走
{writecom(0x89);delay(10); //计时写入1602程序
writedate(table1[dismiao]);
writecom(0x88);delay(10);
writedate(table1[dismiaoshi]);
writecom(0x86);delay(10);
writedate(table1[disfen]);
writecom(0x85);delay(10);
writedate(table1[disfenshi]);
writecom(0x83);delay(10);
writedate(table1[disshi]);
writecom(0x82);delay(10);
writedate(table1[disshishi]);
}
if(P2_3==0&P2_0==1)//定时判断
{ dingshi++;
delay(50000);
}
if(P2_0==0&P2_3==1) //设定判断
{
sheding++;
delay(50000);
}
if(sheding==3) //设定判断成功
{ sheding=0;
P1_7=0;EA=0;
delay(35530);P1_7=1;//
sd=1;
sdyw=1; //设定移位赋初值要在这里赋,若在if(ds==1) 里赋sdyw=1; 总是被执行,这里不要用sdyw_0=1;因为这样其他位不一定为0;
}
if(P2_0==1&sheding!=4) {sheding=0;} //若P20松开后不等于4,sheding要清0,
if(P2_3==1&dingshi!=3) {dingshi=0;} //若P23松开后不等于3,dingshi要清0,
if(dingshi==3) //定时判断成功
{dingshi=0;ds=1;P1_7=0;delay(30000); P1_7=1; dsyw=1; }// 定时标志置1,dsyw=0;dsyw_0=1; 很重要主要让移位有规律
if(ds==1)//进入定时程序
{
dscz=1;
if(P2_1==0) //定时移位
{
P1_7=0;
dsyw=_crol_(dsyw,1);
delay(20000); // 这里delay(20000);可以防抖
P1_7=1;
}
if(dsyw_4==1){dsyw=1;}//这里不要写dsyw_0=1;否则下次移位 dsyw_5=1;
dsmiao=0;dsmiaoshi=0;
if(P2_2==0&dsyw_0==1){dsdisfen++;if(dsdisfen==10){dsdisfen=0;}delay(20000);}
if(P2_2==0&dsyw_1==1){dsdisfenshi++;if(dsdisfenshi==6){dsdisfenshi=0;}delay(20000);}
if(P2_2==0&dsyw_2==1){dsdisshi++;if(dsdisshi==10){dsdisshi=0;}delay(20000);}
if(P2_2==0&dsyw_3==1){dsdisshishi++;if(dsdisshishi==3){dsdisshishi=0;}delay(20000);}
if(dsdisshishi==2&dsdisshi>3){dsdisshishi=0;dsdisshi=0;}
writecom(0x89);delay(10); //定时写入1602程序
writedate(table1[dsmiao]);
writecom(0x88);delay(10);
writedate(table1[dsmiaoshi]);
writecom(0x86);delay(10);
writedate(table1[dsdisfen]);
writecom(0x85);delay(10);
writedate(table1[dsdisfenshi]);
writecom(0x83);delay(10);
writedate(table1[dsdisshi]);
writecom(0x82);delay(10);
writedate(table1[dsdisshishi]);
if(P2_3==0)
{P1_7=0;
delay(5000);P1_7=1;ds=0;
}
}//定时退出
if(sd==1)//设定程序开始
{
if(P2_1==0) //设定移位
{
P1_7=0;
sdyw=_crol_(sdyw,1);
delay(20000) ; // 这里delay(20000);可以防抖
P1_7=1;
if(sdyw_4==1){sdyw=1;}//这里最好不要用sdyw_0=1;这样当sdyw_4=1时再移一位就成sdyw_0=1;sdyw_5也等于1
}
if(P2_2==0&sdyw_0==1){disfen++;if(disfen==10){disfen=0;}delay(20000);} //以下为设定用
if(P2_2==0&sdyw_1==1){disfenshi++;if(disfenshi==6){disfenshi=0;}delay(20000);}
if(P2_2==0&sdyw_2==1){disshi++;if(disshi==10){disshi=0;}delay(20000);}
if(P2_2==0&sdyw_3==1){disshishi++;if(disshishi==3){disshishi=0;}delay(20000);}
if(disshishi==2&disshi==4){disshishi=0;disshi=0;}
writecom(0x89);delay(10); //设定写入1602
writedate(table1[dismiao]);
writecom(0x88);delay(10);
writedate(table1[dismiaoshi]);
writecom(0x86);delay(10);
writedate(table1[disfen]);
writecom(0x85);delay(10);
writedate(table1[disfenshi]);
writecom(0x83);delay(10);
writedate(table1[disshi]);
writecom(0x82);delay(10);
writedate(table1[disshishi]); //设定写入程序到此
if(P2_0==0) //设定好按P00退出
{
EA=1;sd=0;
P1_7=0;
delay(5000);P1_7=1;
}
} //退出设定程序
if(dscz==1&ds==0)
{
if(disshi==dsdisshi&disshishi==dsdisshishi&disfen==dsdisfen&disfenshi==dsdisfenshi) //定时时间到
{P1_7=!P1_7;delay(30000);P1_7=!P1_7;delay(30000);}
}
}
}
void time() interrupt 3 //中断服务
{
TH1=(65536-46050)/256;
TL1=(65536-46050)%256;
count++;
if(count==20) //时分秒计算,放在这里计时准,直接中断控制,在while(1)里计时受其他程序影响
{
count=0;
dismiao++;
if(dismiao==10){dismiaoshi++;dismiao=0;} //dismiao,disfen,disshi,等这些数据在退出while(1)函数后再回来都会变为0,
if(dismiaoshi==6){dismiaoshi=0;disfen++;}
if(disfen==10){disfen=0;disfenshi++;}
if(disfenshi==6){disfenshi=0;disshi++;}
if(disshi==10){disshi=0;disshishi++;}
if(disshishi==2&disshi==4){disshishi=0;disshi=0;}
} //if(count==19)循环到此
}
delay(uint x )//延时子函数
{
uint a;
for(a=x;a>0;a--);
}
AT89S52下载协议是SPI总线格式的4根线
用一个USPASP就可以下载程序了
现在淘宝上大把
AT89S52也支持传统高压编程,也就是并行编程
这个要那个大型的编程器,不怎么方便。
在做单片机的程序,由于串口不够,需要用IO口来模拟出一个串口。经过若干曲折并参考了一些现有的资料,基本上完成了。现在将完整的测试程序,以及其中一些需要总结的部分贴出来。
程序硬件平台:110592M晶振,
/
在单片机上模拟了一个串口,使用P21作为发送端
把单片机中存放的数据通过P21作为串口TXD发送出去
/
#include <reg51h>
#include <stdioh>
#include <stringh>
typedef unsigned char uchar;
int i;
uchar code info[] =
{
0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55
};
sbit newTXD = P2^1;//模拟串口的发送端设为P21
void UartInit()
{
SCON = 0x50; // SCON: serail mode 1, 8-bit UART
TMOD |= 0x21; // T0工作在方式1,十六位定时
PCON |= 0x80; // SMOD=1;
TH0 = 0xFE; // 定时器0初始值,延时417us,目的是令模拟串口的波特率为2400bps fosc=110592MHz
TL0 = 0x7F; // 定时器0初始值,延时417us,目的是令模拟串口的波特率为2400bps fosc=110592MHz
// TH0 = 0xFD; // 定时器0初始值,延时417us,目的是令模拟串口的波特率为2400bps fosc=18432MHz
// TL0 = 0x7F; // 定时器0初始值,延时417us,目的是令模拟串口的波特率为2400bps fosc=18432MHz
}
void WaitTF0(void)
{
while(!TF0);
TF0=0;
TH0=0xFE; // 定时器重装初值 fosc=110592MHz
TL0=0x7F; // 定时器重装初值 fosc=110592MHz
// TH0 = 0xFD; // 定时器重装初值 fosc=18432MHz
// TL0 = 0x7F; // 定时器重装初值 fosc=18432MHz
}
void WByte(uchar input)
{
//发送启始位
uchar j=8;
TR0=1;
newTXD=(bit)0;
WaitTF0();
//发送8位数据位
while(j--)
{
newTXD=(bit)(input&0x01); //先传低位
WaitTF0();
input=input>>1;
}
//发送校验位(无)
//发送结束位
newTXD=(bit)1;
WaitTF0();
TR0=0;
}
void Sendata()
{
for(i=0;i<sizeof(info);i++)//外层循环,遍历数组
{
WByte(info[i]);
}
}
void main()
{
UartInit();
while(1)
{
Sendata();
}
}
##############################################################################
/
模拟接收程序,这个程序的作用从模拟串口接收数据,然后将这些数据发送到实际串口
在单片机上模拟了一个串口,使用P32作为发送和接收端
以P32模拟串口接收端,从模拟串口接收数据发至串口
/
#include<reg51h>
#include<stdioh>
#include<stringh>
typedef unsigned char uchar ;
//这里用来切换晶振频率,支持110592MHz和18432MHz
//#define F18_432
#define F11_0592
uchar tmpbuf2[64]={0};
//用来作为模拟串口接收数据的缓存
struct
{
uchar recv :6 ;//tmpbuf2数组下标,用来将模拟串口接收到的数据存放到tmpbuf2中
uchar send :6 ;//tmpbuf2数组下标,用来将tmpbuf2中的数据发送到串口
}tmpbuf2_point={0,0};
sbit newRXD=P3^2 ;//模拟串口的接收端设为P32
void UartInit()
{
SCON=0x50 ;// SCON: serail mode 1, 8-bit UART
TMOD|=0x21 ;// TMOD: timer 1, mode 2, 8-bit reload,自动装载预置数(自动将TH1送到TL1);T0工作在方式1,十六位定时
PCON|=0x80 ;// SMOD=1;
#ifdef F11_0592
TH1=0xE8 ;// Baud:2400 fosc=110592MHz 2400bps为从串口接收数据的速率
TL1=0xE8 ;// 计数器初始值,fosc=110592MHz 因为TH1一直往TL1送,所以这个初值的意义不大
TH0=0xFF ;// 定时器0初始值,延时208us,目的是令模拟串口的波特率为9600bps fosc=110592MHz
TL0=0xA0 ;// 定时器0初始值,延时208us,目的是令模拟串口的波特率为9600bps fosc=110592MHz
#endif
#ifdef F18_432
TH1=0xD8 ; // Baud:2400 fosc=18432MHz 2400bps为从串口接收数据的速率
TL1=0xD8 ; // 计数器初始值,fosc=18432MHz 因为TH1一直往TL1送,所以这个初值的意义不大
TH0=0xFF ;// 定时器0初始值,延时104us,目的是令模拟串口的波特率为9600bps fosc=18432MHz
TL0=0x60 ;// 定时器0初始值,延时104us,目的是令模拟串口的波特率为9600bps fosc=18432MHz
#endif
IE|=0x81 ;// 中断允许总控制位EA=1;使能外部中断0
TF0=0 ;
IT0=1 ;// 设置外部中断0为边沿触发方式
TR1=1 ;// 启动TIMER1,用于产生波特率
}
void WaitTF0(void)
{
while(!TF0);
TF0=0 ;
#ifdef F11_0592
TH0=0xFF ;// 定时器重装初值 模拟串口的波特率为9600bps fosc=110592MHz
TL0=0xA0 ;// 定时器重装初值 模拟串口的波特率为9600bps fosc=110592MHz
#endif
#ifdef F18_432
TH0=0xFF ;
// 定时器重装初值 fosc=18432MHz
TL0=0x60 ;
// 定时器重装初值 fosc=18432MHz
#endif
}
//接收一个字符
uchar RByte()
{
uchar Output=0 ;
uchar i=8 ;
TR0=1 ; //启动Timer0
#ifdef F11_0592
TH0=0xFF ;// 定时器重装初值 模拟串口的波特率为9600bps fosc=110592MHz
TL0=0xA0 ;// 定时器重装初值 模拟串口的波特率为9600bps fosc=110592MHz
#endif
#ifdef F18_432
TH0=0xFF ;// 定时器重装初值 fosc=18432MHz
TL0=0x60 ;// 定时器重装初值 fosc=18432MHz
#endif
TF0=0 ;
WaitTF0();//等过起始位
//接收8位数据位
while(i--)
{
Output>>=1 ;
if(newRXD)Output|=0x80 ;//先收低位
WaitTF0();//位间延时
}
TR0=0 ;//停止Timer0
return Output ;
}
//向COM1发送一个字符
void SendChar(uchar byteToSend)
{
SBUF=byteToSend ;
while(!TI);
TI=0 ;
}
void main()
{
UartInit();
while(1)
{
if(tmpbuf2_pointrecv!=tmpbuf2_pointsend)//差值表示模拟串口接收数据缓存中还有多少个字节的数据未被处理(发送至串口)
{
SendChar(tmpbuf2[tmpbuf2_pointsend++]);
}
}
}
//外部中断0,说明模拟串口的起始位到来了
void Simulated_Serial_Start()interrupt 0
{
EX0=0 ; //屏蔽外部中断0
tmpbuf2[tmpbuf2_pointrecv++]=RByte(); //从模拟串口读取数据,存放到tmpbuf2数组中
IE0=0 ; //防止外部中断响应2次,防止外部中断函数执行2次
EX0=1 ; //打开外部中断0
}
51单片机超声波DIY
at89S52 在线烧程序要用P15,P16,P17,RST。
这只留出几个脚也没有用啊,要用烧录线,现在只能买USB转ISP的烧录线,而且要向店家说明,是给AT89S52烧录程序的,还要向店家要烧录软件。
现在,给AT89S52烧录程序是很麻烦的事,不如用STC89C52,用USB转TTL模块就搞定了,这种模块,网上可以买到,非常多,也好买。
#include<reg52h>
sbit led = P1^0;
void mian()
{
led = 0;//如果是LED阳极接在单片机上,则是--> led = 1;
while(1);
}
你的学习板是无法实现对AT89S52的烧录的,因为AT89S52不具备“自编程”的功能。
详细说明一下:
AT89S52的烧录模式属于ISP,通俗的说是其它电路直接 *** 作单片机的3根专用的端口完成烧录,属于硬件烧录模式;
而你说用的STC89C52学习板的烧录模式属于IAP,通俗的讲就是单片机通过学习板的串口,接收到需要烧录的程序代码,然后进行“自编程”,姑且叫它软件模式,换句话说只有具备“自编程”性能的单片机才“可能”在你的学习板上完成烧录。
(关于ISP和IAP,可以看一下下面这个连接,里面简单说明了下载烧录的原理,STC的单片机与SST的类似,应该对你有帮助的:>
#include<reg51h>
#define uchar unsigned char
#define LCM_Data P0
#define Busy 0x80 //用于检测LCM状态字中的Busy
sbit RW=P2^1; //定义引脚
sbit RS=P2^0;
sbit EN=P2^2;
sbit int1=P3^3;//定义管脚功能
//sbit cs=P3^2; //使能端
sbit wr=P3^6; //写端口
sbit rd=P3^7; //读端口
unsigned char disp[4]={0,0,0,0};
unsigned char _adc;
void dataproc(unsigned char);
void display(unsigned);
void delay1ms(char);
unsigned char adc0804();
unsigned char v='v';
unsigned char adc0804( ) //读AD0804子程序
{
unsigned char addata,i;
rd=1;
wr=1;
int1=1; //读ADC0804 前准备
P1=0xff; //P1全部置一准备
//cs=0;
wr=0;
wr=1; //启动ADC0804开始测电压
while(int1==1); //查询等待A/D转换完毕产生的INT(低电平有效)信号
rd=0; //开始读转换后数据
i=i; i="i"; //无意义语句,用于延时等待ADC0804 读数完毕
addata=P1; //读出的数据赋与addate
//while(1);
rd=1;
//cs=1; //读数完毕
return(addata); //返回最后读出的数据
}
void dataproc(unsigned char data_in)
{ int results;
results=data_in196;
disp[3]=(results/10000)+0x30;
disp[2]=((results/1000)%10)+0x30;
disp[1]=((results/100)%10)+0x30;
disp[0]=((results/10)%10)+0x30;
}
/lcd1602程序/
void delay1ms(unsigned int ms)//延时1毫秒(不够精确的 ,内部函数)
{unsigned int i,j;
for(i=0;i<ms;i++)
for(j=0;j<100;j++);
}
void wr_com(unsigned char com)//写指令// (内部函数)
{ delay1ms(1);
RS=0;
RW=0;
P0=com;
EN=1;
delay1ms(1);
EN=0;
}
void wr_dat(unsigned char dat)//写数据// (内部函数)
{ delay1ms(1);;
RS=1;
RW=0;
EN=0;
P0=dat;
delay1ms(1);
EN=1;
delay1ms(1);
EN=0;
}
void lcd_init()//初始化设置// (外部调用)
{delay1ms(15);
wr_com(0x38);delay1ms(5);
wr_com(0x08);delay1ms(5);
wr_com(0x01);delay1ms(5);
wr_com(0x06);delay1ms(5);
wr_com(0x0c);delay1ms(5);
}
void main()//主函数
{ while(1)
{
_adc= adc0804( ) ;
dataproc(_adc);
lcd_init();
wr_com(0x80);
wr_dat(disp[3]);
wr_com(0x81);
wr_dat(0x2E);
wr_com(0x82);
wr_dat(disp[2]);
wr_com(0x83);
wr_dat(disp[1]);
wr_com(0x84);
wr_dat(disp[0]);
wr_com(0x85);
wr_dat(v);
//while(1);
}
这是我的程序 我用的0804 但其实都是一样的 呵呵
以上就是关于求AT89S52单片机程序全部的内容,包括:求AT89S52单片机程序、AT89S52单片机怎么下载程序、AT89S52单片机并行转串行c语言程序等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)