|  | 
 
 发表于 2023-5-17 10:57:44
|
显示全部楼层 
| #include "STC8G.h" #include "intrins.h"
 #include "stdio.h"
 #include "tm1640.h"
 
 #define FOSC 11059200L      //11059200L      //System frequency
 #define BAUD 9600           //UART baudrate
 
 /*Define UART parity mode*/
 #define NONE_PARITY     0   //None parity
 #define ODD_PARITY      1   //Odd parity
 #define EVEN_PARITY     2   //Even parity
 #define MARK_PARITY     3   //Mark parity
 #define SPACE_PARITY    4   //Space parity
 #define PARITYBIT EVEN_PARITY   //Testing even parity
 
 /*Define ADC operation const for ADC_CONTR*/
 #define ADC_POWER   0x80            //ADC power control bit
 #define ADC_FLAG    0x20            //ADC complete flag
 #define ADC_START   0x40            //ADC start control bit
 //#define ADC_SPEEDLL 0x00            //420 clocks
 //#define ADC_SPEEDL  0x02            //280 clocks
 //#define ADC_SPEEDH  0x04            //140 clocks
 //#define ADC_SPEEDHH 0x06            //70 clocks
 
 
 //typedef unsigned char uchar;
 //typedef unsigned int uint;
 #define uchar unsigned char           //方便书写
 #define uint  unsigned int
 int ADC_LOW2;
 int val;
 int val1;
 uchar ADC_JS;
 uchar ch = 0;                        //ADC channel NO.
 uchar time1 = 0;                     //ADC中断计时器
 int *BGV;                                        //内部1.19V参考电压值
 char AA=123;
 bit busy;
 bit ADC_O;
 bit play;
 uchar buf[30];
 char temp[20]="电压:";
 uchar TempData[8];     //存储显示值的全局变量
 
 
 sbit RELAY = P3^7; //定义继电器位置
 
 bit KeySensor = 0;                                        //扫描标志
 sbit rst_k1 = P1^2;                                        //设置按钮
 bit rst_k1State = 0;                          //设置
 bit rst_k1Last = 0;                              //设置历史
 bit rst_k1_b = 0;                              //设置标志
 sbit rst_k2 = P1^3;                                        //加一按钮
 bit rst_k2State = 0;                          //加一
 bit rst_k2Last = 0;                              //加一历史
 bit rst_k2_b = 0;                              //加一标志
 sbit rst_k3 = P1^4;                                        //减一按钮
 bit rst_k3State = 0;                          //减一
 bit rst_k3Last = 0;                              //减一历史
 bit rst_k3_b = 0;                              //减一标志
 sbit rst_k4 = P1^5;                                        //确认按钮
 bit rst_k4State = 0;                          //确认
 bit rst_k4Last = 0;                              //确认历史
 bit rst_k4_b = 0;                              //确认标志
 uint KeyCounter;                                  //长按计时
 bit chansu_SYS ;                                   //参数设置标志
 uchar chansu_b = 0;                                //参数设置标号
 uchar V_L;                                                //低压设置值
 uchar V_H;                                                //高压设置值
 uint wengding;                                                //稳定延时设置值
 
 #define sysset                4                        //系统参数2总数
 uchar MemorySys[sysset];                        //系统参数
 
 /*----------------------------
 eeprom关闭
 ----------------------------*/
 
 void IapIdle()
 {
 IAP_CONTR = 0;                              //关闭IAP功能
 IAP_CMD = 0;                                //清除命令寄存器
 IAP_TRIG = 0;                               //清除触发寄存器
 IAP_ADDRH = 0x80;                           //将地址设置到非IAP区域
 IAP_ADDRL = 0;
 }
 /*----------------------------
 eeprom读取
 ----------------------------*/
 
 char IapRead(int addr)
 {
 char dat;
 
 IAP_CONTR = 0x80;                           //使能IAP
 IAP_TPS = 12;                               //设置等待参数12MHz
 IAP_CMD = 1;                                //设置IAP读命令
 IAP_ADDRL = addr;                           //设置IAP低地址
 IAP_ADDRH = addr >> 8;                      //设置IAP高地址
 IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
 IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
 _nop_();
 dat = IAP_DATA;                             //读IAP数据
 IapIdle();                                  //关闭IAP功能
 
 return dat;
 }
 //读取Eeprom中的运行参数数据,以便程序调用
 void EepromRead(unsigned int Eeprom_Address, unsigned char MaxPara, uchar *P)
 {
 unsigned char i;
 //        DelayMS(5);
 
 for( i=0; i<MaxPara; i++ )
 {
 //                *P =(unsigned int)(IapRead(Eeprom_Address+i*2))*0xFF+IapRead(Eeprom_Address+1+i*2);    //读Eeprom的值,存到read_Eeprom
 *P =IapRead(Eeprom_Address+i)  ;
 P++;
 }
 }
 
 /*----------------------------
 eeprom写入
 ----------------------------*/
 void IapProgram(int addr, char dat)
 {
 IAP_CONTR = 0x80;                           //使能IAP
 IAP_TPS = 12;                               //设置等待参数12MHz
 IAP_CMD = 2;                                //设置IAP写命令
 IAP_ADDRL = addr;                           //设置IAP低地址
 IAP_ADDRH = addr >> 8;                      //设置IAP高地址
 IAP_DATA = dat;                             //写IAP数据
 IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
 IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
 _nop_();
 IapIdle();                                  //关闭IAP功能
 }
 //存储系统参数,以便将来应用
 void EepromSave(unsigned int Eeprom_Address, unsigned char MaxPara, uchar *P)
 {
 unsigned char i;
 //        DelayMS(10);
 
 //        Sector_Erase(Eeprom_Address);                   //擦除扇区        这次把擦除扇区写在程序外面,可以先全部擦除再写入
 
 
 for( i=0; i<MaxPara; i++ )
 {
 //                IapProgram(Eeprom_Address+i*2,(unsigned char)( *P /0xFF));
 //                IapProgram(Eeprom_Address+i*2+1,(unsigned char)( *P %0xFF));
 IapProgram(Eeprom_Address+i,*P);
 P++;
 }
 }
 /*----------------------------
 eeprom擦除
 ----------------------------*/
 void IapErase(int addr)
 {
 IAP_CONTR = 0x80;                           //使能IAP
 IAP_TPS = 12;                               //设置等待参数12MHz
 IAP_CMD = 3;                                //设置IAP擦除命令
 IAP_ADDRL = addr;                           //设置IAP低地址
 IAP_ADDRH = addr >> 8;                      //设置IAP高地址
 IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
 IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
 _nop_();                                    //
 IapIdle();                                  //关闭IAP功能
 }
 
 
 
 
 /*----------------------------
 发送一个字符
 ----------------------------*/
 void SendData(uchar dat)
 {
 while (busy);           //Wait for the completion of the previous data is sent
 ACC = dat;              //Calculate the even parity bit P (PSW.0)
 if (P)                  //Set the parity bit according to P
 {
 #if (PARITYBIT == ODD_PARITY)
 TB8 = 0;            //Set parity bit to 0
 #elif (PARITYBIT == EVEN_PARITY)
 TB8 = 1;            //Set parity bit to 1
 #endif
 }
 else
 {
 #if (PARITYBIT == ODD_PARITY)
 TB8 = 1;            //Set parity bit to 1
 #elif (PARITYBIT == EVEN_PARITY)
 TB8 = 0;            //Set parity bit to 0
 #endif
 }
 busy = 1;
 SBUF = ACC;             //Send data to UART buffer
 
 }
 
 
 /*发送字符串*/
 
 void send_string(char *s)
 {
 while (*s)              //Check the end of the string
 {
 SendData(*s++);     //Send current char and increment string ptr
 }
 }
 
 
 void delayms(uint MS)   //
 {
 uchar a;
 uint b;
 for(b=MS;b>0;b--)
 for(a=113;a>0;a--);
 }
 
 /*****将数字转化为字符,发送到串口*****/
 void NumToStr(uint Data, unsigned char Num)
 {
 uchar i;
 
 for( i=5+Num; i>5; i--)
 {
 temp[i] = Data%10 + 0x30;
 Data = Data / 10;
 }
 
 }
 
 /*****将数字拆分,以便显示*****/
 void NumToStr1(uint Data, unsigned char Num)
 {
 uchar i;
 
 for( i=Num; i>0; i--)
 {
 data1[i] = Data%10;
 Data = Data / 10;
 }
 
 }
 
 void KeySensor0(void) //设置按钮
 {
 bit KeyTem;
 KeyTem = rst_k1;
 if( KeyTem == rst_k1Last )
 {
 
 if(KeyTem == 1)
 {
 KeyCounter = 0;
 rst_k1_b=0;
 }
 if(KeyTem == 0)
 {
 KeyCounter++;                                                         //长按进入参数查看状态
 if(KeyCounter>2000 )
 {
 chansu_SYS = 1;                                                //参数设置标志
 chansu_b = 1;                                                   //参数号
 
 }
 if(KeyCounter<2000 && chansu_SYS == 1 &&  rst_k1_b==0)
 {
 chansu_b ++;
 rst_k1_b=1;
 if(chansu_b>4)
 {
 chansu_b = 1;
 
 }
 
 }
 
 }
 
 }
 
 
 rst_k1Last = KeyTem;
 }
 
 void KeySensor1(void) //加一按钮
 {
 bit KeyTem;
 KeyTem = rst_k2;
 if( KeyTem == rst_k2Last )
 {
 
 if(KeyTem == 0 && chansu_SYS == 1 &&  rst_k2_b==0)
 {
 rst_k2_b=1;
 if(chansu_b == 1)
 {
 MemorySys[0]++;
 if(MemorySys[0]>150)
 {
 MemorySys[0]=150 ;
 }
 
 
 }
 if(chansu_b == 2)
 {
 MemorySys[1]++;
 if(MemorySys[1]>220)
 {
 MemorySys[1] =220;
 }
 
 
 }
 if(chansu_b == 3)
 {
 MemorySys[2]++;
 if(MemorySys[2]>100)
 {
 MemorySys[2]=100 ;
 }
 
 
 }
 
 }
 else if(KeyTem == 1)
 {
 rst_k2_b=0;
 }
 
 }
 
 
 rst_k2Last = KeyTem;
 }
 void KeySensor2(void) //减一按钮
 {
 bit KeyTem;
 KeyTem = rst_k3;
 if( KeyTem == rst_k3Last )
 {
 
 if(KeyTem == 0 && chansu_SYS == 1 &&  rst_k3_b==0)
 {
 rst_k3_b=1;
 if(chansu_b == 1)
 {
 MemorySys[0]--;
 if(MemorySys[0]<50)
 {
 MemorySys[0]=50 ;
 }
 
 
 }
 if(chansu_b == 2)
 {
 MemorySys[1]--;
 if(MemorySys[1]<150)
 {
 MemorySys[1]=150 ;
 }
 
 
 }
 if(chansu_b == 3)
 {
 MemorySys[2]--;
 if(MemorySys[2]<10)
 {
 MemorySys[2]=10 ;
 }
 
 
 }
 
 }
 else if(KeyTem == 1)
 {
 rst_k3_b=0;
 
 }
 }
 
 
 rst_k3Last = KeyTem;
 }
 void KeySensor3(void) //确认按钮
 {
 bit KeyTem;
 KeyTem = rst_k4;
 if( KeyTem == rst_k4Last )
 {
 
 if(KeyTem == 0 && chansu_SYS == 1 &&  rst_k4_b==0)
 {
 rst_k4_b=1;
 if(chansu_b < 4)
 {
 chansu_b ++;
 
 }
 else
 {
 chansu_SYS = 0;
 IapErase(0x0000);                                                                //擦除第一扇区
 EepromSave(0x0000, sysset, MemorySys);                        //保存系统参数
 
 }
 
 }
 else if(KeyTem == 1)
 {
 rst_k4_b=0;
 }
 
 }
 
 
 rst_k4Last = KeyTem;
 }
 /*----------------------------
 按键扫描
 ----------------------------*/
 void KeyScan(void)
 {
 
 
 
 KeySensor0();                  //
 KeySensor1();
 KeySensor2();
 KeySensor3();
 play=1;
 //        KeySensor4();
 
 }
 
 
 /*----------------------------
 ADC初始化
 ----------------------------*/
 void InitADC()
 {
 
 
 P_SW2 |= 0x80;
 ADCTIM = 0x3f;                              //设置ADC内部时序
 P_SW2 &= 0x7f;
 ADCCFG = 0x0f;                              //设置ADC时钟为系统时钟/2/16  | ADC_SPEEDLL
 //    ADC_CONTR = 0x80;                         //使能ADC模块
 ADC_RES = 0;                                                                  //清ADC转化结果
 ADC_CONTR = ADC_POWER;                                  //  使能ADC电源
 delayms(2);                       //ADC power-on delay and Start A/D conversion
 }
 
 /*----------------------------
 初始化Uart通讯
 ----------------------------*/
 void InitUart()
 {
 
 PCON &= 0x7F;                //波特率不倍速
 SCON = 0x50;                //8位数据,可变波特率
 AUXR |= 0x40;                //定时器1时钟1T模式
 AUXR &= 0xFE;                //串口1选择定时器1为波特率发生器
 TMOD = 0x00;        //定时器0模式0 定时器1为波特率发生器
 TMOD &= 0x0F;                //清除T1的控制位
 TMOD |= 0x20;                //T1的工作模式2
 //        TH1 = TL1 = -(FOSC/12/32/BAUD); //12T 8位自动重装载
 TH1 = TL1 = -(FOSC/32/BAUD); //1T 8位自动重装载
 //        TL1 = 0xDC;                        //设置定时初始值
 //        TH1 = 0xDC;                        //设置定时重载值
 ET1 = 0;                        //禁止定时器中断
 TR1 = 1;                        //定时器1开始计时
 //定时器0设置
 TL0 = 0x00;                                 //定时器0  12T  65536-11.0592M/12/100
 TH0 = 0xDC;
 TR0 = 1;                                    //启动定时器0
 ET0 = 1;                                    //使能定时器中断
 EADC = 1;           //ADC中断允许位
 ES = 1;                 //Enable UART interrupt
 EA = 1;                 //Open master interrupt switch
 EA = 1;
 }
 
 
 
 
 
 
 
 
 
 
 
 void IniCPU(void)
 {
 P0M0 = 0x00;
 P0M1 = 0x03;                                        //设置P1.1为ADC口
 P1M0 = 0x00;
 P1M1 = 0x00;
 P2M0 = 0x00;
 P2M1 = 0x00;
 P3M0 = 0x00;
 P3M1 = 0x00;
 
 InitUart();
 
 
 
 RELAY = 1;
 }
 /*******************************************************************************
 * 文件名:void VoltageCheckRefresh()
 * 描  述: 电压检测
 * 功  能:
 * 作  者:
 * 版本号:
 *******************************************************************************/
 void VoltageCheckRefresh()
 {
 
 //val = (int)((1024-ADC_LOW2+80)* 6 / 22);        //         (long)((ADC_LOW2) * 5*380/36 / 1024);
 val = 230-val1/4;        //
 //val = val1;        //
 if(val<0)
 {
 val = 0;
 }
 //val =   (int)(1024L*191/ADC_LOW2);            //*BGV
 }
 
 void main()
 {
 
 
 IniCPU();
 BGV=(int idata *)0xef;                                          //参考电压寄存器
 
 EepromRead(0x0000, sysset, MemorySys);        //读取系统参数
 //    send_string("HLW8032 Text!\r\n");
 //        P0=0x0F;
 data1[0]=0;
 data1[1]=1;
 data1[2]=2;
 data1[3]=3;
 ADC_JS=0;
 ADC_O=0;
 InitADC();                      //Init ADC sfr
 ADC_CONTR = ADC_POWER | ADC_START | ch;                          //启动AD转换
 ch = 1;
 val1=0;
 RELAY= 1;
 while(1)
 {
 uint wd;
 if(play==1)
 {
 if(chansu_SYS == 0)
 {
 NumToStr1(val, 3);
 data1[0] = 16;
 tm1640send();
 
 }
 if(chansu_SYS == 1)
 {
 if(chansu_b == 1)
 {
 NumToStr1(MemorySys[0], 3);
 data1[0] = 1;
 tm1640send();
 
 }
 if(chansu_b == 2)
 {
 NumToStr1(MemorySys[1], 3);
 data1[0] = 2;
 tm1640send();
 
 
 }
 if(chansu_b == 3)
 {
 NumToStr1(MemorySys[2], 3);
 data1[0] = 3;
 tm1640send();
 
 
 }
 
 }
 
 play=0;
 }
 if( KeySensor != 0 )                                                        //按键扫描
 {
 KeyScan();
 }
 if(ADC_O==1)
 {
 
 if(ADC_JS>10)
 {
 val1=val1/(ADC_JS-1);
 VoltageCheckRefresh();                                         //计算电压值
 play=1;
 NumToStr(val, 5);
 send_string(temp);
 
 if(val<MemorySys[0])                                   //掉电检测
 {
 RELAY= 1;
 wd=0;
 }
 if(val>MemorySys[1])                                   //来电检测
 {
 //        if(RELAY== 1)
 //        {
 //wd++;
 //if((wengding*10)<wd)
 //{
 RELAY= 0;
 wd=0;
 
 //}
 
 
 //        }
 
 }
 val1=0;
 ADC_JS = 0;
 }
 else
 {
 val1=ADC_LOW2+val1;
 
 }
 
 
 ADC_O=0;
 
 
 }
 if(time1>=1)                 //ADC转换,10ms一次
 {
 ADC_RES = 0;                                                                  //清ADC转化结果
 ADC_CONTR = ADC_POWER | ADC_START | ch;
 
 time1 = 0;
 }
 
 
 
 
 
 
 }
 
 }
 
 
 
 /*----------------------------
 ADC 中断处理
 ----------------------------*/
 void adc_isr() interrupt 5
 {
 ADC_CONTR &= !ADC_FLAG;         //Clear ADC interrupt flag
 ADC_LOW2= ADC_RES;
 ADC_LOW2 <<= 2;
 ADC_LOW2 |= ADC_RESL;
 ADC_JS++;
 ADC_O=1;
 
 //    if (++ch > 7) ch = 0;           //switch to next channel
 ADC_CONTR = ADC_POWER  | ch;
 }
 
 
 #define ADC_POWER   0x80            //ADC power control bit
 #define ADC_FLAG    0x20            //ADC complete flag
 #define ADC_START   0x40            //ADC start control bit
 /*----------------------------
 定时器0 中断处理
 ----------------------------*/
 void TM0_10ms() interrupt 1
 {
 time1++;
 KeySensor = 1;
 
 }
 
 /*串口中断处理函数*/
 void Uart_Isr() interrupt 4
 {
 
 if(RI)
 {
 RI = 0;
 }
 
 if (TI)
 {
 TI = 0;             //Clear transmit interrupt flag
 busy = 0;           //Clear transmit busy flag
 }
 }
 完整的程序
 | 
 |