用是STCD 15W404AS 做主控,片內資源用到了,可調PWM,ADC , 串口(用來讀取計量模塊的數據),具體功能,可按鍵調充電功率,1602顯示實時電壓,電流,功率,電能累計,
設計有1602顯示,但是不知道時序寫的還有些問題還是干擾問題,充電的時候就白屏了或者亂碼了,,不充電有時候有時候是正常的,這里還需要調試,目前已經正常充電,電流30A
單片機源程序如下:
- #include <reg52.h>
- #include "intrins.h"
- sfr AUXR = 0x8E; //0000,0000 輔助寄存器
- sfr T2H = 0xD6; //0000,0000 T2高字節
- sfr T2L = 0xD7; //0000,0000 T2低字節
- sfr P0M1 = 0x93;
- sfr P0M0 = 0x94;
- sfr P1M1 = 0x91;
- sfr P1M0 = 0x92;
- sfr P2M1 = 0x95;
- sfr P2M0 = 0x96;
- sfr P3M1 = 0xb1;
- sfr P3M0 = 0xb2;
- sfr P4M1 = 0xb3;
- sfr P4M0 = 0xb4;
- sfr P5M1 = 0xC9;
- sfr P5M0 = 0xCA;
- sfr P6M1 = 0xCB;
- sfr P6M0 = 0xCC;
- sfr P7M1 = 0xE1;
- sfr P7M0 = 0xE2;
- /////////////////////////////////////////////////////////////////////////////////////////////
- //PWM模塊寄存器定義
- sfr P_SW1 = 0xA2; //外設功能切換寄存器1 針腳選擇功能寄存器
- #define CCP_S0 0x10 //P_SW1.4 選擇針腳功能
- #define CCP_S1 0x20 //P_SW1.5 選擇針腳功能
- #define S1_S1 0x80 //P_SW3.6 選擇針腳功能
- #define S1_S0 0x40 //P_SW3.7 選擇針腳功能
- sfr ADC_CONTR = 0xBC; //ADC控制寄存器
- sfr ADC_RES = 0xBD; //ADC高8位結果
- sfr ADC_LOW2 = 0xBE; //ADC低2位結果
- sfr P1ASF = 0x9D; //P1口第2功能控制寄存器
- #define ADC_POWER 0x80 //ADC電源控制位
- #define ADC_FLAG 0x10 //ADC完成標志
- #define ADC_START 0x08 //ADC起始控制位
- #define ADC_SPEEDLL 0x00 //540個時鐘
- #define ADC_SPEEDL 0x20 //360個時鐘
- #define ADC_SPEEDH 0x40 //180個時鐘
- #define ADC_SPEEDHH 0x60 //90個時鐘
-
- sfr CCON = 0xD8; //PCA控制寄存器
- sbit CCF0 = CCON^0; //PCA模塊0中斷標志
- sbit CCF1 = CCON^1; //PCA模塊1中斷標志
- sbit CR = CCON^6; //PCA定時器運行控制位
- sbit CF = CCON^7; //PCA定時器溢出標志
- sfr CMOD = 0xD9; //PCA模式寄存器
- sfr CL = 0xE9; //PCA定時器低字節
- sfr CH = 0xF9; //PCA定時器高字節
- sfr CCAPM0 = 0xDA; //PCA模塊0模式寄存器
- sfr CCAP0L = 0xEA; //PCA模塊0捕獲寄存器 LOW
- sfr CCAP0H = 0xFA; //PCA模塊0捕獲寄存器 HIGH
- sfr CCAPM1 = 0xDB; //PCA模塊1模式寄存器
- sfr CCAP1L = 0xEB; //PCA模塊1捕獲寄存器 LOW
- sfr CCAP1H = 0xFB; //PCA模塊1捕獲寄存器 HIGH
- sfr CCAPM2 = 0xDC; //PCA模塊2模式寄存器
- sfr CCAP2L = 0xEC; //PCA模塊2捕獲寄存器 LOW
- sfr CCAP2H = 0xFC; //PCA模塊2捕獲寄存器 HIGH
- sfr PCA_PWM0 = 0xf2; //PCA模塊0的PWM寄存器
- sfr PCA_PWM1 = 0xf3; //PCA模塊1的PWM寄存器
- sfr PCA_PWM2 = 0xf4; //PCA模塊2的PWM寄存器
- ///////////////////////////////////////////////////////////函數列表、、、、、、、、、、、、、、、、、、、、、、、、、、、
- void UartInit(); //初始化串口
- void Timer0Init(); //初始化T0
- void UartWxd(); //發送數據查詢實時信息
- void jiexibuf(); //解析接受到的數據
- void pwm(); //解析接受到的數據
- void InitADC(); //初始化ADC
- void GetADCResult(); //讀取ADC的值存儲在變量adc里面
- void Delay(unsigned int n); //軟件延時 1.6毫秒左右
- void chongdian(); // 充電流程
- void diannengjisuan();//J計算初始電能并計算已用電能
- void dianliuxuanze(); //按鈕選項電流
- ///////////////////////////////////////////////////////////定義的一些變量、、、、、、、、、、、、、、、、、、、、、、、、、、、
- bit flagTxd = 0; //單字節發送完成標志,用來替代 TXD 中斷標志位
- sbit s1 = P3^3; //切換繼電器
- sbit km = P3^2; //功率繼電器接觸器
- sbit pwmdip = P1^1;
- sbit k1 = P3^0; //按鈕
- //sbit LED = P1^2;
- unsigned char cntRxd = 0; //接收字節計數器
- unsigned char pdata bufRxd[30]; //接收字節緩沖區
- unsigned char code bufWxd[8] ={0x01,0x03,0x00,0x48,0x00,0x0A,0x45,0xDB,};//發送的數據 增加了code關鍵字,此數組寫在程序區減少使用內部內存128K
- unsigned long pdata cnt = 0; //毫秒計數
- unsigned long pdata sec; //秒計數
- //unsigned cha *but;// 發送指針
- unsigned int pdata vcc; // 電壓
- unsigned int pdata vci; // 電流
- unsigned int pdata power; // 功率
- unsigned long pdata kwh=0; // 電能
- unsigned long pdata kwh1; // 初始電能
- unsigned char pw; //設定的空占比%
- unsigned char cp; //充電樁PWM波形 cp電壓采集信號 120
- //// 關于LCD 1602 /////////////////LCD的一些定義
- sfr P5 = 0xC8;
- unsigned char pdata lcd1[16]; //LCD第一行
- unsigned char pdata lcd2[16]; //LCD第二行
- sbit LCD1602_RS = P5^5; //命令、數據選擇 H\L
- sbit LCD1602_E = P5^4; //使能
- unsigned char pdata ki; //電流顯示1表示16A 2表示32A
- #define LCD1602_DATAPINS P1 //定義P1口為數據端
- void LcdWriteCom(unsigned char com); /*LCD1602寫入8位數據子函數*/
- void LcdWriteData(unsigned char dat); /*LCD1602寫入8位數據子函數*/
- void LcdInit(); /*LCD1602初始化子程序*/
- void lcd1602(); //1602顯示刷新
- void Lcd1602_Delay5ms();
- void Lcd1602_Delay1ms();
- void main(){
- P0M0 = 0x00;
- P0M1 = 0x00;
- P1M0 = 0x00;
- P1M1 = 0x00;
- P2M0 = 0x00;
- P2M1 = 0x00;
- P3M0 = 0x00;
- P3M1 = 0x00;
- P4M0 = 0x00;
- P4M1 = 0x00;
- P5M0 = 0x00;
- P5M1 = 0x00;
- P6M0 = 0x00;
- P6M1 = 0x00;
- P7M0 = 0x00;
- P7M1 = 0x00;
- P_SW1=P_SW1|S1_S0;
- EA = 1; //使能總中斷
- ES = 1; //使能串口1中斷
- UartInit(); //初始化串口
- pwm(); //初始化pwm模塊設置
- InitADC(); //初始化ADC
-
- Timer0Init(); //初始化T0
- LcdInit();//初始化lcd
-
- while (1){
- chongdian(); //充電流程
- dianliuxuanze(); //電流選擇函數
-
- if(TF0==1){ //t0溢出的次數
- cnt++;}
- if(pwmdip==1){ //檢測
- GetADCResult(); //讀取刷新ADC的值 cp就是讀取的8位電壓信號
-
- }
- if(cnt>=20000){ //大概1秒鐘,還可以調整
-
- cnt=0;
- sec++;
-
- UartWxd(); //發送電能模塊讀取命令
- jiexibuf(); //解析接受到的數據
- diannengjisuan(); //電能計算函數
- lcd1602(); //lcd顯示
- }
-
- } }
- void chongdian(){ //、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、充電流程
- if(cp>111){ //當cp電壓大于11.1時 狀態1
- s1=1; //小接觸器不吸合 常閉點12V s1
- km=1;
- } //主接觸器不吸合
- if(98>cp && cp>81){ //當cp電壓大于8.1V小于9.8時 狀態2 與車輛已連接
- s1=0; //小接觸器吸合 切換至PWM
- km=1; } //主接觸器不吸合
- if(66>cp && cp>51){ //當cp電壓大于5.1小于6.6時 狀態3 充電中
- s1=0; //小接觸器吸合 切換至PWM
- km=0; //主接觸器吸合 開始充電
-
- }
- }
- void dianliuxuanze(){ //電流選擇初始值16A
- bit i=0; //電流選擇初始值16A
- if (i==1){ //不切換電流16A
- pw=33;
- ki=1;}
- else{pw=60;
- ki=2;} // 切換電流32A
- if(k1==0)
- { Lcd1602_Delay5ms();
- Lcd1602_Delay5ms();
- if(k1==0){
- i=!i;//k1按下置反i
- }
-
- }
- }
- void pwm(){ //PWM程序、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
-
- ACC = P_SW1; //累加器 等于外設寄存器
- ACC &= ~(CCP_S0 | CCP_S1); //CCP_S0=0 CCP_S1=0
- P_SW1 = ACC; //(P1.2/ECI, P1.1/CCP0, P1.0/CCP1, P3.7/CCP2) 讀取累加器的值寫進外設寄存器
- CCON = 0; //初始化PCA控制寄存器
- //PCA定時器停止
- //清除CF標志
- //清除模塊中斷標志
- CL = 0; //復位PCA寄存器
- CH = 0;
- CMOD = 0x04;
- // CMOD = 0x04; //設置PCA時鐘源 t0定時器
- //禁止PCA定時器溢出中斷
- PCA_PWM0 = 0x00; //PCA模塊0工作于8位PWM
- CCAP0H = CCAP0L =255-255*60/100; //PWM0的占空比為87.5% ((100H-20H)/100H) 255-255*設定空占比 /100
- CCAPM0 = 0x42; //00101010 PCA模塊0允許比較功能 使用CCP0腳為可調脈沖輸出 P1.1
- }
- void Timer0Init() //T0作為PWM頻率基準發生
- {
-
- AUXR |= 0x80; //定時器時鐘1T模式
- TMOD &= 0xF0; //設置定時器模式
- TL0 = 0xd5; //設置定時初值 計算方法,65536-晶振/(256*需要頻率)
- TH0 = 0xFf; //設置定時初值
- TR0 = 1; //定時器0開始計時
- ET0 =0; // 禁止T0中斷
- TF0 = 0; //清除TF0標志
- // EA =0; 關閉總總中斷
- CR = 1; } //PCA定時器開始工作
- ///////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // AUXR |= 0x80; //定時器時鐘1T模式
- // TMOD &= 0xF0; //設置定時器模式
- // TL0 = 0xff; //設置定時初值
- // TH0 = 0xf6; //設置定時初值
- // TF0 = 0; //清除TF0標志
- // TR0 = 1; //定時器0開始計時
- /*----------------------------
- 初始化ADC
- ----------------------------*/
- void InitADC() //初始化ADC
- {
- P1ASF = 0x01; //設置P1.0口為AD口
- ADC_RES = 0; //清除結果寄存器
- ADC_CONTR = ADC_POWER | ADC_SPEEDLL;
- Delay(2); //ADC上電并延時
- }
- /*----------------------------
- 讀取ADC結果
- ----------------------------*/
- void GetADCResult()
- { unsigned long y;
- ADC_CONTR = ADC_POWER | ADC_SPEEDLL | 0 | ADC_START; //ADC電源 540個時鐘ADC_SPEEDHH ADC_SPEEDLL 通道號 啟動
- _nop_(); //等待4個NOP
- _nop_();
- _nop_();
- _nop_();
- while (!(ADC_CONTR & ADC_FLAG));//等待ADC轉換完成
- ADC_CONTR &= ~ADC_FLAG; //Close ADC
-
- //實際濾波測得4.6V一下不予處理
- if(ADC_RES>0x64){
- y=12000000/256*(ADC_RES+1); //ADC結果轉換 單位是最大12000毫伏
- cp=y/100000; //結果轉換120v 放大10倍最大電壓
- }
- }
- void jiexibuf() //解析接受到的數據
- { unsigned long h;
- unsigned long j;
- unsigned long l;
- unsigned long o;
- vcc = (bufRxd[3]<<8)| bufRxd[4]; //電壓 int16位
- vci = (bufRxd[5]<<8)| bufRxd[6]; //電流 int16位
- power = (bufRxd[7]<<8)| bufRxd[8]; //功率 int16位
- h = (bufRxd[9]<<8)| bufRxd[10];//電能 32位數據高16位
- j = (bufRxd[11]<<8)|bufRxd[12];//電能 32位數據低16位
- l = h<<16;
- o = (l|j)*100;
- kwh = o/3200;
- }
- void diannengjisuan() //計算電能顯示函數
- { unsigned long x;
- static bit p=1;
-
- if(p==1){ //開始初始電能記錄
- if(s1==0){ //刷新是否有電能數據
- x=kwh1; // 初始電能傳給x
- p=0; //退出初始電能記錄
- }
- }
- // kwh=kwh1-x;
- }
- void UartInit() //4800bps@11.0592MHz
- {
- // P_SW1=P_SW1|S1_S0;
- SCON = 0x50; //8位數據,可變波特率
- AUXR |= 0x01; //串口1選擇定時器2為波特率發生器
- AUXR |= 0x04; //定時器2時鐘為Fosc,即1T
- T2L = 0xC0; //設定定時初值
- T2H = 0xFD; //設定定時初值
- AUXR |= 0x10; //啟動定時器2
- }
- void UartWxd(){
- unsigned char u; //數據位置 bufWxd[u]
- for(u=0;u<=7;u++)
- {
- flagTxd=0;
- SBUF=bufWxd[u]; // SBUF=bufWxd[u];
- while(!flagTxd);
-
- }
- }
- /*----------------------------
- 軟件延時
- ----------------------------*/
- void Delay(unsigned int n)
- {
- unsigned int x;
- while (n--)
- {
- x = 5000;
- while (x--);
- }
- }
- void InterruptUART() interrupt 4{
- if (RI){ //接收到字節
- RI = 0; //手動清零接收中斷標志位
- bufRxd[cntRxd++] = SBUF; //接收的數據存到接收緩沖區,數組
- if(cntRxd==25){ //接收24幀數據,然后復位接收計數器,下次從0開始接收
- cntRxd=0;
- }
- }
- if (TI){ //字節發送完畢
- TI = 0; //手動清零發送中斷標志位
- flagTxd = 1; //設置字節發送完成標志
- }
- }
- //清中斷標志/清中斷標志
- //void PCA_isr() interrupt 7
- //{
- // CCF0 = 0; //清中斷標志
- // CCAP0L = value;
- // CCAP0H = value >> 8; //更新比較值
- // value += T100Hz;
- // if (cnt-- == 0)
- // {
- // cnt = 100; //記數100次
- // PCA_LED = !PCA_LED; //每秒閃爍一次
- // }
- //}
- //// 關于LCD 1602 LCD 1602 LCD 1602 LCD 1602 LCD 1602 LCD 1602 LCD 1602 /////////////////LCD的一些定義
- void LcdWriteCom(unsigned char com) //寫入命令
- {
- LCD1602_E = 0; //使能清零
- LCD1602_RS = 0; //選擇寫入命令
- LCD1602_DATAPINS = com >>2; //由于4位的接線是接到P0口的高四位,所以傳送高四位不用改
- Lcd1602_Delay1ms();
- LCD1602_E = 1; //寫入時序
- Lcd1602_Delay5ms();
- LCD1602_E = 0;
- LCD1602_DATAPINS = com << 2; //發送低四位
- Lcd1602_Delay1ms();
- LCD1602_E = 1; //寫入時序
- Lcd1602_Delay5ms();
- LCD1602_E = 0;
- }
- void LcdWriteData(unsigned char dat) //寫入數據
- {
- LCD1602_E = 0; //使能清零
- LCD1602_RS = 1; //選擇寫入數據
- // LCD1602_RW = 0; //選擇寫入
-
-
- LCD1602_DATAPINS = dat >>2; //由于4位的接線是接到P0口的高四位,所以傳送高四位不用改
- Lcd1602_Delay1ms();
- LCD1602_E = 1; //寫入時序
- Lcd1602_Delay5ms();
- LCD1602_E = 0;
- LCD1602_DATAPINS = dat << 2; //寫入低四位
- Lcd1602_Delay1ms();
- LCD1602_E = 1; //寫入時序
- Lcd1602_Delay5ms();
- LCD1602_E = 0;
- }
- void LcdInit() //LCD初始化子程序
- {
- Delay(20);
- LcdWriteCom(0x32); //將8位總線轉為4位總線
- LcdWriteCom(0x28); //在四位線下的初始化
- LcdWriteCom(0x0c); //開顯示不顯示光標
- LcdWriteCom(0x06); //寫一個指針加1
- LcdWriteCom(0x01); //清屏
- //LcdWriteCom(0x80); //設置數據指針起點
- }
- void lcd1602()
- { LcdWriteCom(0x80); //設置數據指針起點
- LcdWriteData('V');
- LcdWriteData(':');
- LcdWriteData('0'+vcc/10000%10);
- LcdWriteData('0'+vcc/1000%10);
- LcdWriteData('0'+vcc/100%10);
- LcdWriteData('.');
- LcdWriteData('0'+vcc/10%10);
- LcdWriteData('0'+vcc%10);
- LcdWriteData(' ');
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
51hei截圖20210116100025.png (120.18 KB, 下載次數: 56)
下載附件
2021-1-16 10:00 上傳
51hei.png (5.02 KB, 下載次數: 55)
下載附件
2021-1-16 16:06 上傳
所有程序51hei提供下載:
485 - 通訊程序加顯示.zip
(53.37 KB, 下載次數: 131)
2021-1-16 09:49 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|