📄 main.lst
字号:
C51 COMPILER V7.06 MAIN 09/06/2007 20:26:21 PAGE 1
C51 COMPILER V7.06, COMPILATION OF MODULE MAIN
OBJECT MODULE PLACED IN main.OBJ
COMPILER INVOKED BY: D:\Program Files\Keil\C51\BIN\C51.EXE main.c BROWSE DEBUG OBJECTEXTEND
stmt level source
1 //文 件 名:main.c
2 //名 称:开关稳压电源
3 //功 能:1.实现与CPLD的通信,从而控制PWM的占空比. 2.实现LCD显示相关信息.
4 // 3.实现对键盘按键的判断和确定相应的操作. 4.实现对电压电流的检测.
5 // 5.实现过载保护功能,电流过大时,切断PWM输出,当排除过流故障后,自动恢复供电
6 // 6.实现用PID算法跟踪电压,实现稳压输出
7 //
8 //接口分配: P1.0--键盘输入信号ADC0口 P1.1--输出电流ADC1检测口
9 // P1.2--输出电压ADC检测口 P1.3和1.4--锋鸣器控制口
10 // P3.7,3.1,3.0--LCD控制端cs,std,sclk P2.2,2.3,2.5和2.6--与CPLD通信口
11 // P3.2--按键中断INT0
12 //
13 //作 者:吕定胜
14 //创建日期:2007-09-03
15 //修改日期:2007-09-04
16
17
18 #include <stc12c5410ad.h>
19 #include "shuju.h"
20 #include "lcd.h"
21 #include "cpld.h"
22
23 sbit fenmingh = P1^3;
24 sbit fenmingl = P1^4;
25 sbit ping = P2^1;
26
27 void InitAll(void)
28 {
29 1 lcdinit(); //LCD显示初始化
30 1
31 1 outcs = 1; //给CPLD一个高电平,禁止输出PWM
32 1 P1M0 = 0xFF;
33 1 P1M1 = 0x18; //设置P1.0~2为高阻输入作ADC输入用,P1.3和1.4为开漏模式,P1.5~7为高阻
34 1 P2M0 = 0x91;
35 1 P2M1 = 0x02;
36 1 P3M0 = 0x78;
37 1 P3M0 = 0x00;
38 1 TMOD = 0x10; //计时器1工作于方式1,用于后面的保护电路计时用
39 1 IPH = 0x01;
40 1 IP = 0x01; //设置按键中断为最高级
41 1 IT0 = 0; //设置按键中断为下降沿有效
42 1 //初始化各个变量值
43 1 fixoutu = 300; //开机输出的初始电压为30V
44 1 Ppid->Proportion = 0.36;//比例常数 Proportional Const
45 1 Ppid->Integral=0.01; //积分常数 Integral Const
46 1 Ppid->Derivative=0.002; //微分常数 Derivative的设定
47 1 Ppid->gpwm = pwm[0]; //Ppid->gpwm的初始值为30V副近
48 1 EA = 1; //开总中断
49 1 EX0 = 1; //开键盘中断
50 1 }
51
52 ////检测输出电压和电流////
53 bit CheckOut(void)
54 {
55 1 unsigned char cous; //采样次数计数用
C51 COMPILER V7.06 MAIN 09/06/2007 20:26:21 PAGE 2
56 1 float outtemp0 = 0;
57 1 outu = 0;
58 1 outi = 0;
59 1 for(cous=0;cous<200;cous++)
60 1 {
61 2 ADC_CONTR = 0xE1; //选择ADC1通道,检测电流值
62 2 EA = 0;
63 2 ADC_CONTR |= 0x08; //启动AD转换
64 2 while(!(ADC_CONTR&0x10)); //AD转换尚未完成,继续等待
65 2 ADC_CONTR = ADC_CONTR&0xE7; //清ADC_FLAG,ADC_START,停止AD转换
66 2 EA = 1;
67 2 if(ADC_LOW2&0x02)
68 2 outtemp0 += table1[ADC_DATA];
69 2 else outtemp0 += table0[ADC_DATA];
70 2 delay_50us(1);
71 2 }
72 1 outi = (outtemp0+2000)/4000; //输出电流求值,扩大100倍保存,比例:5V~2.5A
73 1 if(outi>248) {flagguo = 1;return 1;}
74 1
75 1 outtemp0 = 0;
76 1 for(cous=0;cous<200;cous++)
77 1 {
78 2 ADC_CONTR = 0xE2; //选择ADC2通道
79 2 EA = 0;
80 2 ADC_CONTR |= 0x08; //启动AD转换
81 2 while(!(ADC_CONTR&0x10)); //AD转换尚未完成,继续等待
82 2 ADC_CONTR = ADC_CONTR&0xE7; //清ADC_FLAG,ADC_START,停止AD转换
83 2 EA = 1;
84 2 if(ADC_LOW2&0x02)
85 2 outtemp0 += table1[ADC_DATA];
86 2 else outtemp0 += table0[ADC_DATA];
87 2 delay_50us(1);
88 2 }
89 1 outu = (outtemp0*8-outi*500+10000)/20000; //输出电压求值,扩大10倍保存,比例:5V~40V
90 1 return 0;
91 1 }
92
93
94 //PID算法用来调节输出电压
95 void PIDtiao(void)
96 {
97 1 float dError;
98 1 int tiao;
99 1 Ppid->LastError = (fixoutu-outu);
100 1 Ppid->P = Ppid->Proportion*Ppid->LastError; //比例控制量
101 1 if(Ppid->LastError>4) //差距大于0.4V取消积分
102 1 Ppid->SumError = 0;
103 1 else Ppid->SumError += Ppid->LastError; //积分
104 1 Ppid->I = Ppid->Integral*Ppid->SumError; //积分控制量
105 1 dError = Ppid->LastError - Ppid->PrevError; //当前微分
106 1 Ppid->D = Ppid->Derivative*dError; //微分控制量
107 1 Ppid->PrevError = Ppid->LastError;
108 1 tiao = (int)(Ppid->P+Ppid->D+Ppid->I);
109 1 Ppid->gpwm += tiao;
110 1 if(Ppid->gpwm>480) Ppid->gpwm = 480;
111 1 if(Ppid->gpwm<1) Ppid->gpwm = 0;
112 1 send(Ppid->gpwm);
113 1
114 1 }
115
116 //保护电路
117 void baohu(void)
C51 COMPILER V7.06 MAIN 09/06/2007 20:26:21 PAGE 3
118 {
119 1 // unsigned char i;
120 1 outcs = 1;
121 1 send(0xFFFF);
122 1 fenmingh = 1;
123 1 fenmingl = 0;
124 1 display_coordinate(1,1);
125 1 DisplayListChar("警告!!!! ");
126 1 display_coordinate(2,1);
127 1 DisplayListChar("机器存在故障!! ");
128 1 display_coordinate(3,1);
129 1 DisplayListChar("电流过大!!!! ");
130 1 display_coordinate(4,1);
131 1 DisplayListChar("请排除故障!! ");
132 1 lds:outcs = 1;
133 1 send(0xFFFF);
134 1 timer = 50 ;
135 1 ET1 = 1;
136 1 TH1 = 0x00;
137 1 TL1 = 0x00;
138 1 TR1 = 1;
139 1 WDT_CONTR = 0x37;
140 1 while(timer>1)
141 1 {;}
142 1 TR1 = 0;
143 1 send(Ppid->gpwm);
144 1 outcs = 0;
145 1 delay_50us(6);
146 1 flagguo=CheckOut();
147 1 if(flagguo) goto lds;
148 1 fenmingh = 0;
149 1 clear = 1;
150 1 }
151
152 //主函数
153 void main()
154 {
155 1 WDT_CONTR = 0x37;
156 1 Ppid=&pid; //设置指针变量
157 1 InitAll(); //整机初始化
158 1 display0();
159 1 while(1)
160 1 {
161 2 if(flagpower)
162 2 {
163 3 flagguo=CheckOut(); //检测输出电压
164 3 if(flagguo) baohu();
165 3 zhuang1();
166 3 display();
167 3 PIDtiao();
168 3 }
169 2 else
170 2 {
171 3 outu_list[0]='0';
172 3 outu_list[1]='0';
173 3 outu_list[3]='0';
174 3 outi_list[0]='0';
175 3 outi_list[2]='0';
176 3 outi_list[3]='0';
177 3 display();
178 3 }
179 2 WDT_CONTR = 0x37;
C51 COMPILER V7.06 MAIN 09/06/2007 20:26:21 PAGE 4
180 2 }
181 1 }
182
183
184
185 /////////////////中断服务程序///////////////////////
186 //外部中断0服务子程序,主要用于完成按键的判断操作安排
187 void ex0_int(void) interrupt 0
188 {
189 1 unsigned char i,j;
190 1 ADC_CONTR = 0xE0; //选择ADC0通道
191 1 do
192 1 {
193 2 ADC_CONTR |= 0x08; //启动AD转换
194 2 while(!(ADC_CONTR&0x10)); //AD转换尚未完成,继续等待
195 2 ADC_CONTR = ADC_CONTR&0xE7; //清ADC_FLAG,ADC_START,停止AD转换
196 2 i = ADC_DATA;
197 2 delay_50us1(1);
198 2 ADC_CONTR |= 0x08; //启动AD转换
199 2 while(!(ADC_CONTR&0x10)); //AD转换尚未完成,继续等待
200 2 ADC_CONTR = ADC_CONTR&0xE7; //清ADC_FLAG,ADC_START,停止AD转换
201 2 j = ADC_DATA;
202 2 }while(j!=i);
203 1 j &= 0xFC;
204 1
205 1 switch(j)
206 1 {
207 2 case 0xEC:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -