📄 sy0406.c
字号:
//*******************************************************************
//***此程序为调试通过的源程序
//***由南京赛博电子有限公司提供
//***filename:SY0406.C***//
//***是在sy0306的功能上增加了AT89S52的在线下载功能
//***IIC总线芯片改为24C01
//***串口功能:由89S51键盘P1口发送资料数据“123456B7890”,在数码管
//上显示的同时由再由板上的RS232口上传到PC机上,在荧光屏上显示通信
//***反之也可以由PC的键盘上输入数字下载在单板机上显示出来。
//***定时器0--设定数码管定时扫描。
//***定时器1--设定时钟显示计时。
//***定时器2--设定串行通讯波特率。
//*******************************************************************
#include"at89x52.h"
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define nop _nop_() /* 定义空操作指令 */
sbit SCL=P3^4; /*24C01 CSL接脚=89C51 T0 P3.4*/
sbit SDA=P3^5; /*24C01 SDA接脚=89C51 T1 P3.5*/
bit FLAG0=0; /*设定位标号FLAG0=1键盘扫描回应*/
bit FLAG1=1; /*设定位标号20H.1比较密码回应旗号*/
char m,ptr=0,ptr1=0; /*PTR键盘扫描指标,ptr1显示器扫描指标*/
char a1=0,b1=100,stand=0,m=0; /*宣告变数a1为TIMER0的中断次数,ptr为TIMER1扫描数码管指标*/
bit TSendAddress(uchar slaaddress,uchar subaddress,uchar * s,uchar no); /* 向有子地址器件写入6字节数据函数 */
bit TRcvAddress(uchar slaaddress,uchar subaddress,uchar * s,uchar no); /* 向有子地址器件读取6字节数据函数 */
bit acknow; /* 应答标志位 acknow=1 表示正常响应 acknow=0 表示未响应 */
static const char tab[16]={0x01,0x02,0x03,0x0c, /*键盘码00,01,02,03,*/
0x04,0x05,0x06,0x0d, /*键盘码04,05,06,07,*/
0x07,0x08,0x09,0x0e, /*键盘码08,09,0a,0b,*/
0x0a,0x00,0x0b,0x0f};/*键盘码0c,0d,0e,0f*/
static const char tab1[6]={0x08,0x08,0x08,0x08,0x08,0x08};/*内定密码"888888"*/
char HOUR=12;MIN=0;SEC=0; /*变量数,初始时间设定为12:00:00*/
char disple[8]; /*显示值存放阵列*/
char bufdata[9];
char bufuart[6]; /*串口接收值存放阵列*/
void delay (unsigned int value) /*延时副程式*/
{
while (value!=0) value--; /*10US延时*/
}
void BCD(void); /*BCD码转换副程式*/
void scan(void); /*键盘扫描副程式*/
void clear(void); /*清除按键存放/显示器阵列disple[]副副程式*/
void open(void); /*开门比较密码副程式*/
void read24c02(); /*读24c02的存储值*/
void write24c02(); /*写24c02的存储值*/
void IICSAVE(void); /*设定密码并存入buft[]阵列副程式*/
void disp(void); /*显示存放在disple[]阵列的密码副程式*/
void tserial(void); /*串口serial发送副程式*/
void rserial(void); /*串口serial接收副程式*/
void temp(void);
void Start(); /* 起动总线函数 */
void Stop(); /* 结束总线函数 */
void SendByte(uchar c); /* 8951发数据或地址给8583 字节数据发送函数 */
uchar RcvByte(); /* 8951从24C01读数据字节数据接收函数 */
void Ack(bit a); /* 主机8951应答子函数 */
void xch(void); /*宣告按键存放/显示器阵列disple[]右键滚入副程式*/
void speekclose(void);
/*********************************************************************/
main() /*主程式*/
{
TMOD=0x21; /*TIMER0工作在案MODE1,16位定时器*/
/*TIMER1工作在MODE2,自动重新装载模式*/
/*方式寄存器TMOD___________________________*/
/*| 定时器1 | 定时器1 |*/
/*| GATE|C/T| M1 | M0 | GATE|C/T| M1 | M0 |*/
/*|___________________|___________________|*/
TH1=256-(28800/9600); /*设定传输波特率9600,晶体振荡器=11.059Mhz*/
/*|波特率9600时|SMOD=0|C/T=0|模式=2|自动载入TH1=FD|*/
/*|波特率4800时|SMOD=0|C/T=0|模式=2|自动载入TH1=FA|*/
/*|波特率2400时|SMOD=0|C/T=0|模式=2|自动载入TH1=F4|*/
/*|波特率1200时|SMOD=0|C/T=0|模式=2|自动载入TH1=E8|*/
TH0=(65536-3000)/256; /*设定每隔3000us中断扫描一次数码管*/
TL0=(65536-3000)%256;
TR0=1; /*启动TEMER0*/
// T2MOD=0x02; /*定时器2工作在输出模式*/
T2CON=0x38; /*定时器2工作控制寄存器T2CON_________________*/
/*| TF2|EXF2|RCLK|TCLK|EXEN2|TR2|C/T2|CP/RL2|*/
/*|___________________|_____________________|*/
TL2=0xfd; /*设定传输波特率9600,晶体振荡器=11.059Mhz*/
TH2=0xff; /*设定传输波特率9600,晶体振荡器=11.059Mhz*/
RCAP2L=0xdc; /*设定传输波特率9600,晶体振荡器=11.059Mhz*/
RCAP2H=0xff; /*设定传输波特率9600,晶体振荡器=11.059Mhz*/
TH2=256-(28800/9600); /*设定传输波特率9600,晶体振荡器=11.059Mhz*/
/*|波特率9600时|SMOD=0|C/T=0|模式=2|自动载入TH1=FD|*/
/*|波特率4800时|SMOD=0|C/T=0|模式=2|自动载入TH1=FA|*/
/*|波特率2400时|SMOD=0|C/T=0|模式=2|自动载入TH1=F4|*/
/*|波特率1200时|SMOD=0|C/T=0|模式=2|自动载入TH1=E8|*/
TR2=1; /*启动TEMER2*/
SCON=0x50; /*设定UART工作在MODE3模式,可传送和接收数据 REN=1*/
/*串列控制寄存器SCON_______________________*/
/*| 7 6 5 4 | 3 2 1 0 |*/
/*| SM0| SM1| SM2| REN| TB8| RB8| TI | RI |*/
/*|___________________|___________________|*/
IE=0x9f; /*8是允许中断,a是TIMER0,TIMER1中断致能位*/
/*| 7 6 5 4 | 3 2 1 0 |*/
/*| EA | | ET2| ES | ET1| EX1| ET0| EX0|*/
/*|___________________|___________________|*/
IP=0x10; /*中断优先级寄存器IP_______________________*/
/*| | | PT2| PS | PT1| PX1| PT0| PX0|*/
/*|___________________|___________________|*/
read24c02(); /*呼叫读取密码存放在DATE1[]副程式*/
clear(); /*清除数码管,显示为000000副程式*/
P2_0=1; /*关喇叭灭指示灯*/
while(1)
{
scan(); /*呼叫键盘扫描副程式有按FLAG0会为1*/
if(FLAG0==1) temp(); /*判断有按键输入否?*/
delay(300);
nop;
}
}
/***********************************************************************/
void temp(void)
{
if(tab[ptr]==0x0e) disp(); /*如果是按“C”则呼叫显示密码DISP*/
else /*否则往下执行*/
{
switch(tab[ptr]) /*是则测试ptr键盘扫描计数器指标至TAB[]取到的键盘码*/
{
case 0x0a:
write24c02(); /*是否按“*”是则呼叫设定密码SET*/
clear(); /*是否按“#”是则呼叫清除显示器CLEAR*/
break; /*跳出此循环*/
case 0x0b:
clear(); /*是否按“#”是则呼叫清除显示器CLEAR*/
break; /*跳出此循环*/
case 0x0c: /*是否按“A”,未规划键待用户自己定义*/
break; /*跳出此循环*/
case 0x0d: /*是否按“B”,未规划键待用户自己定义*/
break; /*跳出此循环*/
case 0x0e: /*是否按“C”,已侦测过*/
read24c02(); /*呼叫读取密码存放在DATE1[]副程式*/
break; /*跳出此循环*/
case 0x0f: open(); /*是否按“D”,是则呼比较密码开门副程式*/
break; /*跳出此循环*/
default: xch(); /*以上均不是则为数字键呼叫XCH作右键滚入*/
break; /*跳出此循环*/
} /*跳出SWITCH*/
delay(100); /*按钮抗机械反弹跳*/
while(m==P1); /*按钮放开否?*/
delay(100);
}
}
/****************************************************/
void xch(void) /*显示向右移动副程式*/
{
char c; /*宣告变数*/
for(c=5;c>0;c--)
{
disple[c]=disple[c-1]; /*将显示器disple[]移位交换,disple[3]->disple[4]->disple[5]...*/
}
disple[0]=tab[ptr]; /*新的按键值存入disple[0]*/
} /*返回主程式*/
/******************************************************/
void clear(void) /*清除显示器disple[]为00副程式*/
{
char c; /*宣告变数*/
for(c=0;c<6;c++) /*将00存入显示阵列disple[]*/
{
disple[c]=0x00;
} /*返回主程式*/
}
/******************************************************/
void read24c02() /*读24c02的存储值*/
{
uchar i;
TRcvAddress(0xa0,0,&bufdata[0],6);
for(i=0;i<6;i++)
{
disple[i]=bufdata[i];
}
}
/******************************************************/
void write24c02() /*写24c02的存储值*/
{
// uchar i;
TSendAddress(0xa0,0,disple,6); /* 向有子地址器件写入6字节数据函数 */
}
//**************************************************************
void tserial(void) /*宣告串口serial发送副程式*/
{
uchar i=6;
IE=0x8f;
{while(i>0)
{
i--;
SBUF=disple[i]; /*根据扫描指标到TAB中取ASCII码由SBUF发送出去*/
while(TI!=1); /*发送完成否?*/
TI=0; /*是,则清除发送完成旗标TI=0*/
delay(10);
}
}
IE=0x9f;
}
/*--------------------------------------*/
void BCD(void) /*BCD码转换副程式*/
{
char c1; /**/
c1=SEC; /*除60取余数为SEC秒*/
SEC=c1%60; /*除60取余数为SEC秒*/
c1=MIN+c1/60; /*"分"加上秒的进位*/
MIN=c1%60; /*除60取余数为MIN分*/
HOUR=(HOUR+c1/60)%24; /*"时"加上分的进位除24取余数为HOUR时*/
disple[0]=(SEC%10); /*取秒的个位数存入disple[0]*/
disple[1]=(SEC/10); /*取秒的十位数存入disple[1]*/
disple[2]=(MIN%10); /*取分的个位数存入disple[2]*/
disple[3]=(MIN/10); /*取分的十位数存入disple[3]*/
disple[4]=(HOUR%10); /*取时的个位数存入disple[4]*/
disple[5]=(HOUR/10); /*取时的十位数存入disple[5]*/
}
/*******************************************************************
起动总线函数
函数原型: void Start();
功能: 启动总线,发送24c02启动条件.
********************************************************************/
void Start()
{SDA=0;
nop;
nop;
SCL=0;
SDA=1; /*发送起始条件的数据信号*/
nop;
SCL=1;
nop; /*起始条件建立时间大于4.7us,延时*/
nop;
nop;
nop;
nop;
SDA=0; /*发送起始信号*/
nop; /* 起始条件锁定时间大于4us*/
nop;
nop;
nop;
nop;
SCL=0; /*钳住总线,准备发送或接收数据 */
nop;
nop;
SDA=1;
}
/*******************************************************************
结束总线函数
函数原型: void Stop();
功能: 结束总线,发送24c02结束条件.
********************************************************************/
void Stop()
{
SCL=0;
SDA=0; /*发送结束条件的数据信号*/
nop; /*发送结束条件的时钟信号*/
SCL=1; /*结束条件建立时间大于4us*/
nop;
nop;
nop;
nop;
SDA=1; /*发送总线结束信号*/
nop;
nop;
nop;
nop;
SCL=0;
}
/*******************************************************************
89C51发数据或地址给24c02 字节数据发送函数
函数原型: void SendByte(uchar c);
功能: 将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对
此状态位进行操作.(不应答或非应答都使acknow=0)
发送数据正常,acknow=1; acknow=0表示被控器无应答或损坏。
********************************************************************/
void SendByte(uchar c)
{
uchar count;
for(count=0;count<8;count++) /*要传送的数据长度为8位*/
{
if((c<<count)&0x80)
SDA=1; /*判断发送位*/
else
SDA=0;
nop;
SCL=1; /*置时钟线为高,通知被控器开始接收数据位*/
nop;
nop; /*保证时钟高电平周期大于4us*/
nop;
nop;
nop;
SCL=0;
}
nop;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -