2012年用STC15F104E做了一些485继电器控制小板,自己自制智能家居。
后面出了104W,就换了104W
后面又出了104WS,就自带串口了。
当时硬是用模拟串口做出来了,可以跑115200bps。
STC15F104W 模拟串口可跑115200bps.C
(14.76 KB, 下载次数: 93)
- #include <reg52.h> //使用8052内核单片机
- #include <intrins.h> //使用_nop_();
- sbit IO1=P3^5; //IO
- sbit IO2=P3^4; //IO
- sbit IO3=P3^3; //IO
- sbit DE_RE=P3^2; //智能家居485总线流控方向,1发送,0接收
- sbit TX_IO=P3^1; //模拟串口发送IO
- sbit RX_IO=P3^0; //模拟串口接收IO
- sfr AUXR=0x8e; //STC15F104E系列单片机特殊寄存器,控制定时器时钟来源频率
- sfr P3M0=0xb2; //P3IO口工作模式
- sfr eeprom_data =0xc2;
- sfr eeprom_addh =0xc3;
- sfr eeprom_addl =0xc4;
- sfr eeprom_cmd =0xc5;
- sfr eeprom_star =0xc6;
- sfr eeprom_cont =0xc7;
-
- bit sending,receing,stpbsed,bytereceived; //发送中,接收中,接收完毕标志
- bit data_receive_enable; //帧头判断成功,过零信号前一状态
- bit trig_count_enable1; //过零信号到达启动计时
- bit trig_count_enable2; //过零信号到达启动计时
- bit traic_1_on,traic_2_on;
- unsigned char rece_bit_count; //接收位计数变量
- unsigned char rece_pls_count; //接收脉冲计数变量
- unsigned char send_bit_count; //发送位计数变量
- unsigned char send_pls_count; //发送脉冲计数变量
- unsigned char receing_data; //正在接收着的临时数据
- unsigned char byte_need_to_send; //要发送出去的字节
- unsigned char byte_received; //已收到的字节
-
- unsigned char zhen_tou[]={0xFF,0x00,0x55,0xAA,0x00,0xFF};//帧头字串
- unsigned char cast_tou[]={0xFF,0x00,0x55,0xAA,0xFF,0x00};//广播地址帧头
-
- unsigned char jie_shou[]={0x00,0x00,0x00,0x00,0x00,0x00};//接收的数据帧
-
- unsigned int code baud[]={0xa000,0xd000,0xe800,0xf400,0xfa00,0xfd00,0xfe00,0xff00,0xff25,0xff80,0xffc0};
- //300-----600----1200---2400---4800---9600---14400--28800--33600--57600--115200
- //smod=1@22.1184mhz,auxr|=0x80
- unsigned char count,checksum,temp; //处理数据帧字节计数,校验和,临时传递变量
- unsigned char etmp1,etmp2; //操作eeprom用的临时保存变量
- unsigned char verify,fr_num; //帧头核对及数据帧接收位置
- unsigned char com_bit_tick; //串口位节拍计时器,主要用作回包延时控制
- unsigned char trig_count1; //移相触发延时变量
- unsigned char trig_count2; //移相触发延时变量
- unsigned char brightness1,brightness2; //可控硅亮度
- unsigned int bootdelay,baud_index; //启动延时,波特率索引值
-
- //eeprom 命令:0空闲,1读字节,2写字节,3扇区擦除
- //写到eeprom_cont 寄存器的值:0x81,小于24MHz
- //eepROM 起始地址:0x0000,0x0000-0x01ff 第一扇区 0x0200-0x03ff第二扇区
- void close_eeprom(void);
- unsigned char read_eeprom(unsigned int addr);
- void write_eeprom(unsigned int addr,dat);
- void erase_eeprom(unsigned int addr);
- void send_byte(unsigned char byte_will_send); //发送一个字节
- unsigned char pack_ana(void);
- void set_baud(unsigned char index);
- void respond_packge(void);
- void execute_cmd(void);
- void byte_reced(void);
- void traic_on_off(void);
- void main(void) //主程序
- { //开始
- unsigned long btn_push_count;
- P3=0XCF;
- AUXR=0xc0; //T0计时脉冲不分频,比传统8051快12倍
- P3M0=0X3c;//00111100
- TMOD=0X00; //16位自动重载模式,当TR0=0时向TH0,TL0写入数据将同时写入重载寄存器
- TH0=0xfd; //重载值=65536-(定时器脉冲频率÷波特率÷3)
- TL0=0x00; //溢出率=定时器脉冲频率÷(65536-重载值)
- TH1=0xFB;
- TL1=0xAE; //50uS@22.1184mhz计数率
- TR0=1; //启动定时器,模拟串口开始工作
- TR1=1; //启动定时器,可控硅移相触发开始工作
- EA=1; //打开总中断
- ET0=1; //打开定时器0中断
- ET1=1; //打开定时器1中断
- PT0=1; //优先保证定时器0中断,确保模拟串口的可靠性
- DE_RE=0;
- bootdelay=15000;
- etmp1=35;
- while(--etmp1)
- {
- while(--bootdelay)
- {
- byte_reced();
- }
- }
- baud_index=read_eeprom(0x0001);
- set_baud(baud_index);
- zhen_tou[4]=read_eeprom(0x0000);
- zhen_tou[5]=~zhen_tou[4];
- brightness1=read_eeprom(0x0200);
- brightness2=read_eeprom(0x0201);
- traic_on_off();
- while(1) //主循环
- { //主循环体开始
- byte_reced();
- if(TX_IO==0)
- {
- while(TX_IO==0)
- {
- btn_push_count++;
- }
- if(btn_push_count>200000 && btn_push_count<500000){IO1=~IO1;}
- if(btn_push_count>500000 && btn_push_count<1500000){IO2=~IO2;}
- if(btn_push_count>1800000){IO3=~IO3;}
- btn_push_count=0;
- }
- //send_byte(0X55);
- } //主循环体结束
- } //主程序结束
- void send_byte(unsigned char byte_will_send) //发送一个字节
- { //函数开始
- byte_need_to_send=byte_will_send; //传递要发送的数据
- send_pls_count=3; //采样倍率3
- send_bit_count=8; //8位数据一位停止
- TX_IO=0; //发送起始位
- sending=1; //置标志位,中断程序开始发送该字节
- stpbsed=0;
- while(sending==1); //等待数据发送完成
- } //函数结束
- void timer0(void) interrupt 1 //中断服务程序
- { //函数开始
- // IO3=!IO3;
- if(receing) //接收中?
- { //接收中开始
- if(--rece_pls_count==0) //三次脉冲计数够了吗?
- { //接收一位二进制位开始
- rece_pls_count=3; //脉冲计数辅助变量复位
- if(rece_bit_count) //是在接收数据位还是停止位
- { //接收数据位开始
- receing_data=receing_data>>1; //向右移一位,准备拼入一位二进制数据
- if(RX_IO==1){receing_data=receing_data|0x80;}//如果收到的是二进制位"1",则拼入最高位中
- rece_bit_count=rece_bit_count-1; //已接收一位,接收位计数变量计数
- } //接收数据位结束
- else //如果已经收完8位数据
- { //就开始接收停止位
- receing=0; //本字节已接收完毕
- if(RX_IO==1) //停止位是"1"吗
- { //是“1”
- byte_received=receing_data; //将数据输出
- bytereceived=1;
- //------------------------------------------------//知道了……
- } //数据输出处理完毕
- } //停止位处理完毕
- } //接收一位二进制位结束
- } //接收中处理结束
- else //还没收到停止位,不是正在接收状态
- { //等待接收开始
- if(RX_IO==0) //是一个起始位到来吗
- { //是.......
- receing=1; //开始接收
- rece_pls_count=4; //置接收起始位脉冲数
- rece_bit_count=8; //置接收二进制位数
- } //起始位处理完毕
- } //等待接收完毕
- //----------------------------------------------------------------------------------------
- if(sending) //是正在发送状态吗
- { //是……
- if(--send_pls_count==0) //脉冲计数够了吗
- { //够了……
- send_pls_count=3; //脉冲计数复位
- if(send_bit_count) //是在发送数据还是要发送停止位
- { //发送数据开始
- TX_IO=byte_need_to_send&0x01; //从最低位开始发送数据
- byte_need_to_send=byte_need_to_send>>1; //移动数据准备下一次发送
- send_bit_count=send_bit_count-1; //已经发送了一位二进制数要记下来
- } //发送数据结束
- else //数据已经发送完成
- { //发送停止位开始
- if(stpbsed)
- {
- sending=0; //放下旗帜表示数据已经发送完成
- }
- TX_IO=1; //发送停止位
- stpbsed=1;
- } //停止位发送完成
- } //一位二进制位处理完成
- } //发送状态处理完成
- com_bit_tick--; //串口位时间滴答向下
- } //中断函数结束
- void timer1(void) interrupt 3 //中断服务程序
- {
- if(IO3==0) //一个新的过零信号到来了吗
- {
- trig_count_enable1=1;
- trig_count_enable2=1;
- }
- if(traic_1_on==1)
- {
- IO2=0;
- if(trig_count_enable1==1)
- {
- trig_count1++;
- if(trig_count1>=brightness1)
- {
- trig_count_enable1=0;
- trig_count1=0;
- IO2=1;
- }
- }
- }
- if(traic_2_on==1)
- {
- IO1=0;
- if(trig_count_enable2==1)
- {
- trig_count2++;
- if(trig_count2>=brightness2)
- {
- trig_count_enable2=0;
- trig_count2=0;
- IO1=1;
- }
- }
- }
- }
- unsigned char pack_ana(void)
- {
- checksum=0;
- for(count=0;count<6;count++)
- {
- checksum=checksum+zhen_tou[count];
- }
- for(count=0;count<5;count++)
- {
- checksum=checksum+jie_shou[count];
- }
- if(checksum==jie_shou[5])
- {
- return(1);
- }
- else
- {
- return(0);
- }
- }
- void set_baud(unsigned char index)
- {
- if(index>10) //faild value
- {
- index=5;
- }
- TR0=0; //启动定时器,模拟串口开始工作
- TH0=baud[index]/256; //重载值=65536-(定时器脉冲频率÷波特率÷3)
- TL0=baud[index]%256; //溢出率=定时器脉冲频率÷(65536-重载值)
- TR0=1; //启动定时器,模拟串口开始工作
- baud_index=index;
- }
- void respond_packge(void)
- {
- com_bit_tick=100;
- while(com_bit_tick!=0);
- DE_RE=1; //置75176为发送模式
- checksum=0;
- for(count=0;count<6;count++)
- {
- temp=zhen_tou[count];
- send_byte(temp);
- checksum=checksum+temp;
- }
- for(count=0;count<5;count++)
- {
- checksum=checksum+jie_shou[count];
- }
- jie_shou[5]=checksum;
- for(count=0;count<6;count++)
- {
- send_byte(jie_shou[count]);
- }
- DE_RE=0; //置75176为接收模式
- }
- void execute_cmd(void)
- {
- if(jie_shou[0]==0x00)//断开继电器命令
- {
- if(jie_shou[1]==0x00){IO1=0;}//关闭一号继电器
- if(jie_shou[1]==0x01){IO2=0;}//关闭二号继电器
- if(jie_shou[1]==0x02){IO3=0;}//关闭三号继电器
- if(jie_shou[4]==0x01){respond_packge();}
- }
- if(jie_shou[0]==0x01)//接通继电器命令
- {
- if(jie_shou[1]==0x00){IO1=1;}//闭合一号继电器
- if(jie_shou[1]==0x01){IO2=1;}//闭合二号继电器
- if(jie_shou[1]==0x02){IO3=1;}//闭合三号继电器
- if(jie_shou[4]==0x01){respond_packge();}
- }
- if(jie_shou[0]==0x02)//查询继电器命令
- {
- if(jie_shou[1]==0x00){if(IO1==1){jie_shou[2]=0x01;}else{jie_shou[2]=0x00;}}
- if(jie_shou[1]==0x01){if(IO2==1){jie_shou[2]=0x01;}else{jie_shou[2]=0x00;}}
- if(jie_shou[1]==0x02){if(IO3==1){jie_shou[2]=0x01;}else{jie_shou[2]=0x00;}}
- respond_packge();
- }
- //---------------------
- if(jie_shou[0]==0x03)//设置可控硅1亮度命令
- {
- brightness1=200-jie_shou[1];
- traic_on_off();
- if(jie_shou[4]==0x01){respond_packge();}
- }
- if(jie_shou[0]==0x04)//设置可控硅2亮度命令
- {
- brightness2=200-jie_shou[1];
- traic_on_off();
- if(jie_shou[4]==0x01){respond_packge();}
- }
- //---------------------
- if(jie_shou[0]==0x05)//设置并保存可控硅1亮度命令
- {
- IO1=IO2=traic_1_on=traic_2_on=0;
- brightness1=200-jie_shou[1];//计算亮度值
- etmp1=read_eeprom(0x0201);//读出第二通道可控硅亮度值进行保护
- erase_eeprom(0x0200);//擦除EEPROM
- write_eeprom(0x0200,brightness1);//写入新的第一通道可控硅值
- write_eeprom(0x0201,etmp1);//写回第二通道可控硅值
- traic_on_off();//判断是否启用可控硅控制
- if(jie_shou[4]==0x01){respond_packge();}
- }
- if(jie_shou[0]==0x06)//设置并保存可控硅2亮度命令
- {
- IO1=IO2=traic_1_on=traic_2_on=0;
- brightness2=200-jie_shou[1];
- etmp1=read_eeprom(0x0200);//读出第一通道可控硅亮度值进行保护
- erase_eeprom(0x0200);//擦除EEPROM
- write_eeprom(0x0201,brightness2);//写入新的第二通道可控硅值
- write_eeprom(0x0200,etmp1);//写回第一通道可控硅值
- traic_on_off();//判断是否启用可控硅控制
- if(jie_shou[4]==0x01){respond_packge();}
- }
- //---------------------
- if(jie_shou[0]==0x10)//断开继电器命令,为了兼容485继电器模块的命令
- {
- IO1=0;
- if(jie_shou[4]==0x01){respond_packge();}
- }
- if(jie_shou[0]==0x11)//接通继电器命令,为了兼容485继电器模块的命令
- {
- IO1=1;
- if(jie_shou[4]==0x01){respond_packge();}
- }
- if(jie_shou[0]==0x12)//查询继电器命令,为了兼容485继电器模块的命令
- {
- if(IO1==1)
- {
- jie_shou[1]=0x01;
- }
- else
- {
- jie_shou[1]=0x00;
- }
- respond_packge();
- }
- //---------------------
- if(jie_shou[0]==0x15)//查询从机地址
- {
- jie_shou[1]=read_eeprom(0x0000);
- jie_shou[2]=~jie_shou[1];
- respond_packge();
- }
- if(jie_shou[0]==0x16)//修改从机地址
- {
- etmp2=read_eeprom(0x0001);
- erase_eeprom(0x0000);
- write_eeprom(0x0000,jie_shou[1]);
- write_eeprom(0x0001,etmp2);
- zhen_tou[4]=jie_shou[1];
- zhen_tou[5]=~jie_shou[1];
- if(jie_shou[4]==0x01){respond_packge();}
- }
- if(jie_shou[0]==0x18)//查询从机波特率
- {
- jie_shou[1]=read_eeprom(0x0001);
- if(jie_shou[1]>10)
- {
- jie_shou[1]=5;
- }
- respond_packge();
- }
- if(jie_shou[0]==0x17)//设置从机波特率
- {
- if(jie_shou[1]>10)
- {
- jie_shou[1]=5;
- }
- etmp1=read_eeprom(0x0000);
- erase_eeprom(0x0000);
- write_eeprom(0x0000,etmp1);
- write_eeprom(0x0001,jie_shou[1]);
- set_baud(jie_shou[1]);
- if(jie_shou[4]==0x01){respond_packge();}
- }
- }
- void close_eeprom(void)
- {
- eeprom_cont=0;
- eeprom_cmd=0;
- eeprom_star=0;
- eeprom_addh=0x80;
- eeprom_addl=0x00;
- }
- unsigned char read_eeprom(unsigned int addr)
- {
- unsigned char dat;
- eeprom_cont=0x81;
- eeprom_cmd=1;
- eeprom_addl=addr&0xff;
- eeprom_addh=addr>>8;
- eeprom_star=0x5a;
- eeprom_star=0xa5;
- _nop_();
- _nop_();
- _nop_();
- dat=eeprom_data;
- close_eeprom();
- return(dat);
- }
- void write_eeprom(unsigned int addr,dat)
- {
- eeprom_cont=0x81;
- eeprom_cmd=2;
- eeprom_addl=addr&0xff;
- eeprom_addh=addr>>8;
- eeprom_data=dat;
- eeprom_star=0x5a;
- eeprom_star=0xa5;
- _nop_();
- _nop_();
- _nop_();
- close_eeprom();
- }
- void erase_eeprom(unsigned int addr)
- {
- eeprom_cont=0x81;
- eeprom_cmd=3;
- eeprom_addl=addr&0xff;
- eeprom_addh=addr>>8;
- eeprom_star=0x5a;
- eeprom_star=0xa5;
- _nop_();
- _nop_();
- _nop_();
- close_eeprom();
- }
- void byte_reced(void)
- {
- if(bytereceived==1)
- {
- bytereceived=0;
- if(data_receive_enable)
- {
- jie_shou[fr_num]=byte_received;
- fr_num++;
- if(fr_num>=6)
- {
- data_receive_enable=0;
- fr_num=0;
- if(pack_ana()==1)
- {
- execute_cmd();
- }
- }
- }
- else
- {
- if( (zhen_tou[verify]==byte_received) || (cast_tou[verify]==byte_received))
- {
- verify++;
- if(verify>=6)
- {
- data_receive_enable=1;
- verify=0;
- }
- }
- else
- {
- verify=0;
- data_receive_enable=0;
- if(zhen_tou[verify]==byte_received)
- {
- verify=1;
- }
- }
- }
- //------------------------------------------------//
- }
- }
- void traic_on_off(void)
- {
- if(brightness1>=200){brightness1=199;traic_1_on=0;}else{traic_1_on=1;}
- if(brightness2>=200){brightness2=199;traic_2_on=0;}else{traic_2_on=1;}
- if(traic_1_on==1 || traic_2_on==1){P3M0=0X36;}else{P3M0=0x3c;}
- }
复制代码
|