程序已完成及測試後反應良好,傳上來給大家參詳指教:
STC15F104E 只有 2 個普通時鐘可用,所以要寫個模擬 PWM 的軟件。
先定下 PWM 的頻率為 2kHz,選系統頻率為 10MHz,由此計算到每周期分為 5000 格。低光度用 25% 脈寬,中光度用 50% 脈寬,高光度是全亮,程序如下:
此程序非常簡單, 只使用兩個中斷:PWM 用計時器 0, 磁控管接外部中斷 1
/**************************************************************
PROGRAM NAME :Torch.c
DESCRIPTION :A program to control a torch with
:4 levels of brightness -- off-low-mid-high
MCU :STC15F104E
FREQUENCY :Internal RC osc 10MHz
MODIFTY DATE :2012/05/24
**************************************************************/
1 #include <reg51.h>
2 #include <intrins.h>
3
4 #define LightOff PWMOut=0 //low to turn off the light
5 #define LightOn PWMOut=1 //high to turn on the light
6
7 sfr P3M0 = 0xb2;
8 sfr AUXR = 0x8e;
9 sbit PWMOut = P3^2;
10 sbit KeyIn = P3^3;
11
12 //PWM frequency = 2KHz, so total count of a cycle is 5000
13 code int Brightness[2][2] = {{3750, 1250}, {2500, 2500}};
14 char BrightnessL[4];
15 char BrightnessH[4];
16 char LightLevel; //0=off 1=low 2=mid 3=high
17
18 void Delay(unsigned int Times);
19
20 void main(void)
21 {
22 BrightnessL[0] = (65536 - Brightness[0][0]) % 256;
23 BrightnessH[0] = (65536 - Brightness[0][0]) / 256;
24 BrightnessL[1] = (65536 - Brightness[0][1]) % 256;
25 BrightnessH[1] = (65536 - Brightness[0][1]) / 256;
26 BrightnessL[2] = (65536 - Brightness[1][0]) % 256;
27 BrightnessH[2] = (65536 - Brightness[1][0]) / 256;
28 BrightnessL[3] = (65536 - Brightness[1][1]) % 256;
29 BrightnessH[3] = (65536 - Brightness[1][1]) / 256;
30
31 KeyIn = 1;
32 LightLevel = 0; //light off when power on
33 PWMOut = 0;
34 AUXR = 0x80; //set Timer0 to 1T
35 P3M0 = 0x04; //set P3.2 to PP for output
36
37 //Timer0 init
38 TMOD = 0x01; //set timer0 to 16-bit counter
39 IT1 = 1; //set int1 falling only
40 IE = 0xc6; //set bit EA, ELVD, EX1, ET0
41 PT0 = 1;
42
43 PCON = 0x02;
44 _nop_();
45 _nop_();
46 _nop_();
47 while(1);
48 }
49
50 void Timer0Int(void) interrupt 1
51 {
52 switch (LightLevel)
53 {
54 case 1:
55 if (PWMOut)
56 {
57 PWMOut = 0;
58 TL0 = BrightnessL[0];
59 TH0 = BrightnessH[0];
60 }
61 else
62 {
63 PWMOut = 1;
64 TL0 = BrightnessL[1];
65 TH0 = BrightnessH[1];
66 }
67 break;
68
69 case 2:
70 if (PWMOut)
71 {
72 PWMOut = 0;
73 TL0 = BrightnessL[2];
74 TH0 = BrightnessH[2];
75 }
76 else
77 {
78 PWMOut = 1;
79 TL0 = BrightnessL[3];
80 TH0 = BrightnessH[3];
81 }
82 break;
83
84 case 3:
85 LightOn;
86 TR0 = 0;
87 }
88 }
89
90 void Ex1Int(void) interrupt 2
91 {
92 EX1 = 0;
93 Delay(7000); //debounce about 100mS
94 if (!KeyIn)
95 {
96 LightLevel++;
97 if (LightLevel > 3)
98 {
99 LightLevel = 0;
100 TR0 = 0;
101 EX1 = 1;
102 LightOff;
103
104 PCON = 0x02;
104 _nop_();
105 _nop_();
106 _nop_();
107 _nop_();
108 }
109 TR0 = 1;
110
111 while (!KeyIn); //wait switch release
112 Delay(7000);
113 }
114 IE0 = 0;
115 EX1 = 1;
116 }
117
118 void Delay(unsigned int Times)
119 {
120 unsigned int i;
121 for (i = 0; i < Times; i++);
122 }
程序說明:
13 行 宣告 PWM 的兩組控制光度的參數,第 1 組是 25% 寬度,第2組是 50% 寬度
22~29 行 因懶惰將PWM的數據交編譯器計算成計時器使用的數據
43 行 電源接通後先進入電源下降模式
47 行 初始工作完成後,進入無限迴圈
50 行 時鐘0中斷程式,視變數 LightLevel 的數值,作控制 PWM 寬度用
90 行 磁控管輸入中斷程式,可看到 LightLevel = 0時,電筒進入電源下降模式
|