【简要说明】
尺寸:长107mmX宽85mmX高18mm
二、主要芯片:STC8A8K64S4A12单片机(可替换为STC8A8K64D4)、CH340 、SP485
三、工作电压:直流5~36伏
四、支持:UATR接口下载程序及USB下载(需要安卓接口线) 五、特点:
1、具有电源指示功能;
2、所以I/O口以引出并有LED灯做信号指示;
3、可以实现与电脑串口通信、TTL通讯及RS485通讯;
4、内部多晶振选择使用
5、输出IO口指示灯可以用短路帽控制;
6、宽电压供电支持5~36V供电最大稳压输出电流1.5A;
7、四路按键输入方便调试程序;
8、采用螺旋端子压接,接线可靠方便扩展;
9、调试程序方便,适合工程使用;
10、供电具有防反接保护。电路工作稳定可靠;
开发板测试程序 附件资料里面有工程文件
【声明】此程序仅用于学习与参考!
*********************************************************************/
#include <STC8.h>
#include <intrins.h>
#define uchar unsigned char//宏定义无符号字符型
#define uint unsigned int //宏定义无符号整型
unsigned char T0RH = 0; //T0重载值的高字节
unsigned char T0RL = 0; //T0重载值的低字节
bit flagFrame = 0; //帧接收完成标志,即接收到一帧新数据
bit flagTxd = 0; //单字节发送完成标志,用来替代TXD中断标志位
unsigned char cntRxd = 0; //接收字节计数器
unsigned char pdata bufRxd[100]; //接收字节缓冲区
void UartDriver();//串口驱动函数,监测数据帧的接收,调度功能函数,需在主循环中调用
void UartAction(unsigned char *buf, unsigned char len);//在接收到的数据帧后添加换车换行符后发回
void UartWrite(unsigned char *buf, unsigned char len);//串口数据写入,即串口发送函数,buf-待发送数据的指针,len-指定的发送长度
unsigned char UartRead(unsigned char *buf, unsigned char len);//串口数据读取函数,buf-接收指针,len-指定的读取长度,返回值-实际读到的长度
void UartRxMonitor(unsigned char ms);//串口接收监控,由空闲时间判定帧结束,需在定时中断中调用,ms-定时间隔
void ConfigUART();//串口配置函数,baud-通信波特率
void ConfigTimer0(unsigned int ms);//配置并启动T0,ms-T0定时时间
uchar send[50],sendlen=0;
uchar ck1=0x00;
/********************************************************************
初始定义
*********************************************************************/
sbit po5 = P3^4;
sbit po6 = P3^5;
sbit po7 = P3^6;
sbit po8 = P3^7;
sbit de1 = P1^0;
sbit de2 = P1^1;
sbit de3 = P1^2;
sbit de4 = P1^3;
sbit de5 = P1^4;
sbit de6 = P1^5;
sbit de7 = P1^6;
sbit de8 = P1^7;
sbit d1 = P2^0;
sbit d2 = P2^1;
sbit d3 = P2^2;
sbit d4 = P2^3;
sbit d5 = P2^4;
sbit d6 = P2^5;
sbit d7 = P2^6;
sbit d8 = P2^7;
sbit deng1 = P0^0;
sbit deng2 = P0^1;
sbit deng3 = P0^2;
sbit deng4 = P0^3;
sbit deng5 = P0^4;
sbit deng6 = P0^5;
sbit deng7 = P0^6;
sbit deng8 = P0^7;
sbit den2 = P4^1;
sbit den3 = P4^2;
sbit den4 = P4^3;
sbit den5 = P4^4;
sbit xd1 = P6^0;
sbit xd2 = P6^1;
sbit xd3 = P6^2;
sbit xd4 = P6^3;
sbit xd5 = P6^4;
sbit xd6 = P6^5;
sbit xd7 = P6^6;
sbit xd8 = P6^7;
sbit xxd1 = P7^0;
sbit xxd2 = P7^1;
sbit xxd3 = P7^2;
sbit xxd4 = P7^3;
sbit xxd5 = P7^4;
sbit xxd6 = P7^5;
sbit xxd7 = P7^6;
sbit xxd8 = P7^7;
sbit xxd_9 = P5^2;
sbit xxd_10 = P5^3;
sbit xxd_11 = P5^1;
sbit xxd_12 = P5^0;
sbit aj1 = P5^4;
sbit aj2 = P5^5;
sbit aj3 = P4^0;
sbit aj4 = P3^2;
sbit aj5 = P3^3;
bit ba=0,kt=0,kt_1=0,kt_2=0,kt_3=0,kt_4=0,fa=0,ga=0;
uchar temp,z=0; //定义字符型变量
uchar a,b,i;
uchar trg=0,trg_1=0,trg_2=0,trg_3=0,trg_4=0,cont=0,cont_1=0,cont_2=0,cont_3=0,cont_4=0;
uchar ReadData=0,ReadData_1=0,ReadData_2=0,ReadData_3=0,ReadData_4=0;
void delay()//延时程序
{
uchar m,n,s;
for(m=20;m>0;m--)
for(n=20;n>0;n--)
for(s=248;s>0;s--);
}
void UartAction(unsigned char *buf, unsigned char len){//接收
UartWrite(buf,len); //收到啥发回啥
// if((buf[0]==0xAA)&&(buf[1]==0x01)&&(buf[2]==0xBB)&&(len==3)){//串口接收例子
// p01=0; //长度
// send[ 0]=0xCC;
// send[ 1]=0x01;
// sendlen=2;
// UartWrite(send, sendlen);//发送
// }
}
void KeyRead()//读取按键IO口函数
{
ReadData = aj1^0xff; // 读取按键状态取反后赋值给ReadData
trg = ReadData & (ReadData ^ cont); //trg短按,每按下按键trg=1;抬手后为trg=0,长按为trg=0
cont = ReadData; //cont长按,长按cont=1,抬手后cont=0
ReadData_1 = aj2^0xff; // 读取按键状态取反后赋值给ReadData
trg_1 = ReadData_1 & (ReadData_1 ^ cont_1); //trg短按,每按下按键trg=1;抬手后为trg=0,长按为trg=0
cont_1 = ReadData_1; //cont长按,长按cont=1,抬手后cont=0
ReadData_2 = aj3^0xff; // 读取按键状态取反后赋值给ReadData
trg_2 = ReadData_2 & (ReadData_2 ^ cont_2); //trg短按,每按下按键trg=1;抬手后为trg=0,长按为trg=0
cont_2 = ReadData_2;
ReadData_3 = aj4^0xff; // 读取按键状态取反后赋值给ReadData
trg_3 = ReadData_3 & (ReadData_3 ^ cont_3); //trg短按,每按下按键trg=1;抬手后为trg=0,长按为trg=0
cont_3 = ReadData_3;
ReadData_4 = aj5^0xff; // 读取按键状态取反后赋值给ReadData
trg_4 = ReadData_4 & (ReadData_4 ^ cont_4); //trg短按,每按下按键trg=1;抬手后为trg=0,长按为trg=0
cont_4 = ReadData_4;
}
void key_1()
{
if(trg & 0x01) //短按
{
kt_3=0;kt_1=0;kt_2=0;kt_4=0;
kt=1; //这是短按标志位,kt=1说明短按了
ba=1;//P1=P3=0XFF; // P1=0xff;
}
if((aj1!=0)&&(kt==1))//判断
{
po5=~po5; //p3.4
po7=~po7; //p3.6
den2=~den2;//p4.1
den3=~den3;//p4.2
d3=~d3;//p2.2
d5=~d5;//p2.4
xd5=~xd5;//p6.4
xd7=~xd7;//p6.6
xxd4=~xxd4;//p7.3
xxd2=~xxd2;//p7.1
xxd_12=~xxd_12;//p5.0
kt=0;
} // 短按
}
void key_2()
{
if(trg_1 & 0x01) //短按
{
kt=0;kt_3=0;kt_2=0;kt_4=0;
kt_1=1; //这是短按标志位,kt=1说明短按了
ba=1;//P1=P3=0XFF;
}
if((aj2!=0)&&(kt_1==1))//判断
{
// po2=~po2;
// po4=~po4;//因为P3.3 P3.2已经为按键使用了,所以不能再控制P3.2 3.3 口了,不然按键无法使用
po6=~po6; //p3.5
po8=~po8; //p3.7
d1=~d1; //p2.0
d2=~d2; //p2.1
d4=~d4; //p2.3
d6=~d6; //p2.5
xd6=~xd6;//p6.5
xd8=~xd8;//p6.7
xxd3=~xxd3;//p7.2
xxd1=~xxd1;//p7.0
xxd_11=~xxd_11;//p5.0
kt_1=0;
} // 短按
}
void key_3()
{
if(trg_2 & 0x01) //短按
{
kt=0;kt_1=0;kt_3=0;kt_4=0;
kt_2=1; //这是短按标志位,kt=1说明短按了
ba=1;//P1=P3=0XFF;
}
if((aj3!=0)&&(kt_2==1))//判断
{
d7=~d7; //p2.6
deng1=~deng1;//p0.0
deng3=~deng3;//p0.2
deng4=~deng4;//p0.3
deng6=~deng6;//p0.5
deng8=~deng8;//p0.7
xxd6=~xxd6;//p7.5
xxd8=~xxd8;//p7.7
kt_2=0;
} // 短按
}
void key_4()
{
if(trg_3 & 0x01) //短按
{
kt=0;kt_1=0;kt_2=0;kt_4=0;
kt_3=1; //这是短按标志位,kt=1说明短按了
ba=1;//P1=P3=0XFF;
}
if((aj4!=0)&&(kt_3==1))//判断
{
d8=~d8;
deng2=~deng2;
den4=~den4;
deng5=~deng5;
deng7=~deng7;
de1=~de1;
de3=~de3;
de5=~de5;
de6=~de6;
de8=~de8;
xxd5=~xxd5;//p7.4
xxd7=~xxd7;//p7.6
xxd_10=~xxd_10;//p5.3
xd1=~xd1;//p6.0
xd3=~xd3;//p6.2
kt_3=0;
} // 短按
}
void key_5()
{
if(trg_4 & 0x01) //短按
{
kt=0;kt_1=0;kt_2=0;kt_3=0;
kt_4=1; //这是短按标志位,kt=1说明短按了
ba=1;//P1=P3=0XFF;
}
if((aj5!=0)&&(kt_4==1))//判断
{
de2=~de2;
de4=~de4;
den5=~den5;
de7=~de7;
xxd_9=~xxd_9; //p5.2
xd2=~xd2;//p6.1
xd4=~xd4;//p6.3
kt_4=0;
} // 短按
}
void main(){
EA = 1; //开总中断
ConfigTimer0(1); //配置T0定时1ms
ConfigUART(); //配置波特率为9600
temp=0xfE; //11111110定义每次一个灯亮
while(1){
UartDriver(); //调用串口驱动
if(ba==0)
{
P3=P1=P2=P0=P4=P5=P6=P7=temp;//直接对1/0口赋值,使批输出低电平。
for(i=0;i<9;i++)//实现广告灯的从右到左移动
{
a=temp<<i; //左移i位
P3=P1=P2=P0=P4=P5=P6=P7=a;//相与求值
delay();
delay();
delay();
delay();
delay();
delay();
delay();
delay();
delay();
z++;
}
}
if((z>8)&&(ga==0)){ba=1;P1=P3=P2=P0=P4=P5=P6=P7=0XFF;ga=1;z=0;} //流水一遍结束
// KeyRead();
key_1();
key_2();
key_3();
key_4();
key_5();
}
}
void InterruptTimer0() interrupt 1{//T0中断服务函数,执行串口接收监控
TH0 = T0RH; //重新加载重载值
TL0 = T0RL;
UartRxMonitor(1); //串口接收监
KeyRead();
}
void InterruptUART() interrupt 4{//串口中断服务函数
if (RI) { //接收到新字节
RI = 0; //清零接收中断标志位
if (cntRxd < sizeof(bufRxd)) {//接收缓冲区尚未用完时,保存接收字节,并递增计数器
bufRxd[cntRxd++] = SBUF; // cntRxd++这个很重要,一开始 cntRxd < sizeof(bufRxd)当进入函数的次数增加,cntRxd慢慢变大,当传入的数据不满的时候就 用时间检测,判断是否是传输完成
}
}
if (TI) { //字节发送完毕
TI = 0; //清零发送中断标志位
flagTxd = 1; //设置字节发送完成标志
}
}
void ConfigTimer0(unsigned int ms){//配置并启动T0,ms-T0定时时间
unsigned long tmp; //临时变量
tmp = 11059200 / 12; //定时器计数频率
tmp = (tmp * ms) / 1000; //计算所需的计数值
tmp = 65536 - tmp; //计算定时器重载值
tmp = tmp + 33; //补偿中断响应延时造成的误差
T0RH = (unsigned char)(tmp>>8); //定时器重载值拆分为高低字节
T0RL = (unsigned char)tmp;
TMOD &= 0xF0; //清零T0的控制位
TMOD |= 0x01; //配置T0为模式1
TH0 = T0RH; //加载T0重载值
TL0 = T0RL;
ET0 = 1; //使能T0中断
TR0 = 1; //启动T0
}
void ConfigUART(){//串口配置函数,baud-通信波特率
SCON = 0x50; //8位数据,可变波特率
AUXR |= 0x01; //串口1选择定时器2为波特率发生器
AUXR |= 0x04; //定时器2时钟为Fosc,即1T
T2L = 0xE0; //设定定时初值
T2H = 0xFE; //设定定时初值
AUXR |= 0x10; //启动定时器2
ES = 1; //使能串口中断
}
void UartWrite(unsigned char *buf, unsigned char len){//串口数据写入,即串口发送函数,buf-待发送数据的指针,len-指定的发送长度
while (len--){ //循环发送所有字节
flagTxd = 0; //清零发送标志
SBUF = *buf++; //发送一个字节数据
while (!flagTxd); //等待该字节发送完成
}
}
unsigned char UartRead(unsigned char *buf, unsigned char len){//串口数据读取函数,buf-接收指针,len-指定的读取长度,返回值-实际读到的长度
unsigned char i;
if (len > cntRxd){ //指定读取长度大于实际接收到的数据长度时,读取长度设置为实际接收到的数据长度
len = cntRxd;
}
for (i=0; i<len; i++){ //拷贝接收到的数据到接收指针上
*buf++ = bufRxd;
}
cntRxd = 0; //接收计数器清零
return len; //返回实际读取长度
}
void UartDriver(){//串口驱动函数,监测数据帧的接收,调度功能函数,需在主循环中调用
unsigned char len;
unsigned char pdata buf[40];
if (flagFrame){ //有命令到达时,读取处理该命令
flagFrame = 0;
len = UartRead(buf, sizeof(buf)-2); //将接收到的命令读取到缓冲区中
UartAction(buf, len); //传递数据帧,调用动作执行函数
}
}
void UartRxMonitor(unsigned char ms){//串口接收监控,由空闲时间判定帧结束,需在定时中断中调用,ms-定时间隔
static unsigned char cntbkp = 0;
static unsigned char idletmr = 0;
if (cntRxd > 0){ //接收计数器大于零时,监控总线空闲时间
if (cntbkp != cntRxd){ //接收计数器改变,即刚接收到数据时,清零空闲计时
cntbkp = cntRxd;
idletmr = 0;
}else{ //接收计数器未改变,即总线空闲时,累积空闲时间
if (idletmr < 30){ //空闲计时小于30ms时,持续累加
idletmr += ms;
if (idletmr >= 30){ //空闲时间达到30ms时,即判定为一帧接收完毕
flagFrame = 1; //设置帧接收完成标志
}
}
}
}else{
cntbkp = 0;
}
}
|