STC单片机实现可调PWM输出的C51程序

合集下载

STC单片机PWM的实现

STC单片机PWM的实现

STC单片机PWM的实现实现PWM功能的步骤如下:1.设置计时器/计数器模式:选择一个适当的计时器/计数器模式,通常选择16位定时器模式,然后配置相关寄存器。

2.设置计时器的初值:将计时器的计数初值设置为0。

3.设置计时器的重载值:根据所需的PWM周期确定计时器的重载值,设置到重载寄存器中。

4.设置计时器的工作模式:选择适当的计时器工作模式,通常选择自动重载模式或单次计数模式。

5.设置PWM占空比:根据所需的PWM占空比计算出所需要的计数值,并将其设置到计时器寄存器中。

6.启动计时器:将计时器使能位设置为1,启动计时器。

7.等待PWM周期结束:等待计时器溢出,表示一个PWM周期结束。

8.关闭计时器:将计时器使能位清零,关闭计时器。

通过以上步骤,就可以在STC单片机上实现PWM功能。

下面是一个具体的实例,以STC89C52为例,实现一个简单的PWM控制LED亮度的功能:```c#include <reg51.h>sbit PWM_PIN = P1^0; // 控制端口void mainTMOD=0x00;//设置定时器0为模式0,工作方式1 TH0=0xEC;//计时器初值TL0=0xEC;ET0=1;//允许定时器0中断TR0=1;//启动定时器0while(1)//控制PWM占空比,0-255之间,控制LED亮度for(int i = 0; i < 256; i++)PWM_PIN=1;//设置PWM引脚高电平for(int j = 0; j < i; j++); // 控制占空比PWM_PIN=0;//设置PWM引脚低电平for(int k = 0; k < 255-i; k++); // 控制占空比}}void Timer0_ISR( interrupt 1static unsigned char count = 0;count++;//设置重载值,控制PWM频率TH0=0xEC;TL0=0xEC;if(count > 100) // 设置占空比PWM_PIN=0;elsePWM_PIN=1;```以上代码通过控制定时器0的计数值和PWM引脚的电平状态实现了一个简单的PWM控制LED亮度的功能。

51单片机——增强型PWM,使用自带PWM发生器

51单片机——增强型PWM,使用自带PWM发生器

51单片机——增强型PWM,使用自带PWM发生器0. 序之前用定时器做了模拟PWM输出,得到的1k左右波形还行,到10k往上波形就特别难看,又是跳变又是长短不一。

后来在参考手册上面看到stc15w4k系列自带pwm波形发生器,于是整了好久写出来了。

今天因为业务需求要改代码,回头一看,好家伙,都不知道自己写的啥了。

看了一会儿想起来,于是有了此文。

1. 简介如图,如下介绍,他直接把PWM输出到IO口上面,我使用的是这两个,于是就用了PWM3和PWM2_2两个。

2. 分析占坑,今天还要重构代码,改很多东西,暂时不分析了(2021.6.2)。

3. 代码代码比较简单,我是照着这个写的,XDM自己去瞅瞅啊,我当时看了一早上才看明白。

1.#include <STC15.H> //52头文件2.#include <PWM.H>3.4.u8 Tcount=0; //一个PWM周期内的:周期计数,占空比,方向5.sbit PWM = P2^1;//PWM4口6.sbit PWM2 = P2^7; //PWM2口7.sbit NPWM1 =P5^4; //关闭PWM异常口8.sbit NPWM2 =P5^4; //关闭PWM异常口9.void setPWMWide(u8 Wide); //设置脉宽10.11.#define CYCLE 0x800L//5khz //定义PWM周期(最大值为32767)12.#define DUTY1 20 //定义占空比为20%13.#define DUTY2 30 //定义占空比为30%14.#define DUTY3 50 //定义占空比为50%15.16.//主函数17.void InitPWM()18.{19.InterruptInit();//初始化中断配置20.}21.22.void setPWMWide(u8 Wide)23.{24.P_SW2 |= 0x80; //使能访问XSFR25.PWMIF=0x00;26.PWMFDCR = 0x00; //关闭PWM异常检测,P5.4和P5.5在IIC中使用,如果不关闭会一直进入异常导致无法设置PWM占空比27.PWMCFG = 0x00; //配置PWM的输出初始电平为低电平28.PWMCKS = 0x00; //选择PWM的时钟为Fosc/(0+1)29.PWMC = CYCLE; //设置PWM周期30.31.//板子PWM4 芯片PWM2_2 P2.732.// PWM2T1 = 0x0000; //设置PWM2第1次反转的PWM计数33.// PWM2T2 = CYCLE * DUTY / 100; //设置PWM2第2次反转的PWM计数34.PWM2T1 = 0x0000; //设置PWM2第1次反转的PWM计数35.PWM2T2 = CYCLE * (Wide) / 100; //设置PWM2第2次反转的PWM计数36.PWM2CR |= 0x08; //选择PWM2输出到P2.7,不使能PWM2中断37.38.PWM3T1 = 0x0000; //设置PWM2第1次反转的PWM计数39.PWM3T2 = CYCLE * (Wide) / 100; //设置PWM2第2次反转的PWM计数40.//占空比为(PWM2T2-PWM2T1)/PWMC41.PWM3CR = 0; //选择PWM2输出到P2.142.43.//使能44.PWMCR = 0x03; //使能PWM信号输出45.PWMCR |= 0x80; //使能PWM模块46.P_SW2 &= ~0x80;47.48.}49.50.void SetPWM(u8 level) //设置风扇等级 1 2 3 4是自动不用管风速51.{52.// PutChar(speedFlag);53.if(level==1) //1是9.8k54.{55.setPWMWide(DUTY1);56.}57.else if(level==2)58.{59.setPWMWide(DUTY2);60.}61.else if(level==3)62.{63.setPWMWide(DUTY3);64.}65.66.}67.68.69.//中断初始化配置70.void InterruptInit()71.{72.73.P2M1 &= 0<<1; //PWM4 P2.1 设置推挽74.P2M0 |= 1<<1;75.P2M1 &= 0<<7; //PWM4 P2.7 设置推挽76.P2M0 |= 1<<7;77.78.PWM=0;79.PWM2=0;80.81.P_SW2 |= 0x80; //使能访问XSFR82.PWMIF=0x00;83.PWMFDCR = 0x00; //关闭PWM异常检测,P5.4和P5.5在IIC中使用,如果不关闭会一直进入异常导致无法设置PWM占空比84.PWMCFG = 0x00; //配置PWM的输出初始电平为低电平85.PWMCKS = 0x00; //选择PWM的时钟为Fosc/(0+1)86.PWMC = CYCLE; //设置PWM周期87.88.//板子PWM4 芯片PWM2_2 P2.789.PWM2T1 = 0x0000; //设置PWM2第1次反转的PWM计数90.PWM2T2 = CYCLE * DUTY1 / 100; //设置PWM2第2次反转的PWM计数91.//占空比为(PWM2T2-PWM2T1)/PWMC92.PWM2CR |= 0x08; //选择PWM2输出到P2.7,不使能PWM2中断93.94.//板子PWM2 芯片PWM3 P2.195.PWM3T1 = 0x0000; //设置PWM2第1次反转的PWM计数96.PWM3T2 = CYCLE * DUTY1 / 100; //设置PWM2第2次反转的PWM计数97.//占空比为(PWM2T2-PWM2T1)/PWMC98.PWM3CR = 0; //选择PWM2输出到P2.199.100.//使能101.PWMCR = 0x03; //使能PWM信号输出102.PWMCR |= 0x80; //使能PWM模块103.P_SW2 &= ~0x80;104.105.}。

C51代码(PWM)

C51代码(PWM)

1. #include < reg51.h >2. #include < intrins.h >3.4. sbit K1 =P1A4 ; // 增加键5. sbit K2 =P"5 ; // 减少键6. sbit P00 =P0A1;7. sbit BEEP =P3A7 ; // 蜂鸣器8. unsigned char PWM=0xe7; // 赋初值9.10. void Beep();11. void delayms(unsigned char ms);12. void delay(unsigned char t);13.14. /*********************************************************/15. void main()16. (17.18. P1=0xff;19. TMOD=0x21 ;20. TH0=0xff ; //50us 延时常数21. TL0=0xce ; //频率调节22.23. TH1=PWM ; 〃脉宽调节24. TL1=0 ;25.26. EA=1;27. ET0=1;28. ET1=1;29.30. TR0=1 ;31.32. while(1)33.34. do(35. if(PWM!=0xff)36. (PWM++ ;delayms(10);)37. else Beep();38.39. while(K1==0);40.41. do(42. if(PWM!=0xce)43. {PWM-- ;delayms(10);}44. else Beep();45.46. while(K2==0);47.48.49.50. void timer0() interrupt 151.52. TR1=0;53. TH0=0xff ;54. TL0=0xce ;55. TH1=PWM ;56. TR1=1 ;57. P00=0 ; //启动输出58.59.60.61. void timer1() interrupt 362.63. TR1=0;64. P00=1 ; //结束输出65. }66./*********************************************************/ 68. //蜂鸣器子程序/*********************************************************/ 70.71. void Beep()72.{ 73.unsigned char i ; 74.for (i=0 ;i<100 ;i++) 75.{ 76.delay(100); 77.BEEP=!BEEP ; //Beep 取反 78.} 79.BEEP=1 ; //关闭蜂鸣器 80.delayms(100); 81.82.} 83. /*********************************************************/ 84. //延时子程序85. /*********************************************************/86. void delay(unsigned char t)87. {88.while(t--) ; 89. 90.}91./*********************************************************/92. //延时子程序/*********************************************************/ voiddelayms(unsigned char ms) 95.96. {67. 69. 93. 94.97. unsigned char i ;98. while(ms--)99. {100. for(i = 0 ; i < 120 ; i++);101. }102. }103.103. /*********************************************************/ 104. #include < reg51.h >105. #include < intrins.h >107.106. sbit K1 =P1A4 ; 〃增加键107. sbit K2 =P1A5 ; 〃减少键108. sbit P00 =P0A1;109. sbit BEEP =P3A7 ; // 蜂鸣器110. unsigned char PWM=0xe7; // 赋初值113.111. void Beep();112. void delayms(unsigned char ms);113. void delay(unsigned char t);117.114. /*********************************************************/ 115. void main()116. {121.117. P1=0xff;118. TMOD=0x21 ;119. TH0=0xff ; 120. TL0=0xce ; 126.121. TH1=PWM ; 122. TL1=0 ; //50us延时常数//频率调节//脉宽调节130. EA=1;131. ET0=1;132. ET1=1;133.133. TR0=1 ;135.134. while(1)135. (136. do{137. if(PWM!=0xff)138. {PWM++ ;delayms(10);} 139. else Beep();140. }141. while(K1==0);144.142. do{143. if(PWM!=0xce)144. {PWM--;delayms(10);} 145. else Beep();146. }147. while(K2==0);148. }149. }153.150. void timer0() interrupt 1151. {152. TR1=0 ;153. TH0=0xff ;154. TL0=0xce ;155. TH1=PWM ;156. TR1=1 ;162. }163. 164. 165. void timer1() interrupt 3166. {169. } 170. 171. /*********************************************************/ 172. //蜂鸣器子程序173. /*********************************************************/ 174.175. void Beep()176.179. delay(100) 182.185.186. 187. /*********************************************************/ 188. //延时子程序189. /*********************************************************/ 190. void delay(unsigned char t)191. {192. while(t--) ;161.P00=0; //启动输出167.TR1=0; 168.P00=1 ; //结束输出177.unsigned char i 178.for (i=0 ;i<100 ;i++)180.181.BEEP=!BEEP ; //Beep 取反 183.BEEP=1 //关闭蜂鸣器184. delayms(100);194.195. /*********************************************************/ 196. //延时子程序197. /*********************************************************/ 198. void delayms(unsigned char ms)199.199. {200. unsigned char i ;201. while(ms--)202. {203. for(i = 0 ; i < 120 ; i++);204. }205. }207.206. /*********************************************************/ 207. #include < reg51.h >208. #include < intrins.h >211.209. sbit K1 =P1A4 ; //增加键210. sbit K2 =P"5 ; //减少键211. sbit P00 =P0A1;212. sbit BEEP =P3A7 ; // 蜂鸣器213. unsigned char PWM=0xe7; // 赋初值217.214. void Beep();215. void delayms(unsigned char ms);216. void delay(unsigned char t);221.217. /*********************************************************/ 218. void main()219. {P1=0xff; TMOD=0x21 ; TH0=0xff ; //50us 延时常数 TL0=0xce ; //频率调节 TH1=PWM ; //脉宽调节 TL1=0 ; EA=1; ET0=1; ET1=1; TR0=1 ; while(1) { do{ if(PWM!=0xff) {PWM++ ;delayms(10);} else Beep(); } while(K1==0); do{ if(PWM!=0xce) {PWM-- ;delayms(10);} else Beep(); } while(K2==0); } }226.227.228.229.230.231.232.233.234.235.236.237.238.239.240.241.242.243.244.245.246.247.248.249.250.251.252.253.254.255.256.258. void timer0() interrupt 1259. (260. TR1=0 ;261. TH0=0xff ;262. TL0=0xce;263. TH1=PWM ;264. TR1=1 ;265. P00=0 ; 〃启动输出266. }267.268.267. void timer1() interrupt 3268. (271. TR1=0;272. P00=1 ; //结束输出273. } 274.275. /*********************************************************/276. //蜂鸣器子程序277. /*********************************************************/ 278.279. void Beep()280. (281. unsigned char i ;282. for (i=0 ;i<100 ;i++)283. (284. delay(100);285. BEEP=!BEEP ; //Beep 取反286. }287. BEEP=1 ; //关闭蜂鸣器288. delayms(100);290.291. /*********************************************************/ 292. //延时子程序293. /*********************************************************/ 294. void delay(unsigned char t)295. {296. while(t--) ;297. }298.298. /*********************************************************/ 299. //延时子程序300. /*********************************************************/ 301. void delayms(unsigned char ms)303.302. {303. unsigned char i ;304. while(ms--)305. {306. for(i = 0 ; i < 120 ; i++);307. }308. }311.309. /*********************************************************/ 310. #include < reg51.h >311. #include < intrins.h >315.312. sbit K1 =P1A4 ; //增加键313. sbit K2 =P"5 ; //减少键314. sbit P00 =P0A1;315. sbit BEEP =P3A7 ; // 蜂鸣器316. unsigned char PWM=0xe7; // 赋初值322. void Beep();323. void delayms(unsigned char ms);324. void delay(unsigned char t);325.326. /*********************************************************/ 327. void main() 328. {329.330. P1=0xff;331. TMOD=0x21 ;332. TH0=0xff ; //50us延时常数333. TL0=0xce ; //频率调节334.335. TH1=PWM ; //脉宽调节336. TL1=0 ;337.338. EA=1;339. ET0=1;340. ET1=1;341.342. TR0=1 ;343.344. while(1)345.346. do{347. if(PWM!=0xff)348. {PWM++ ;delayms(10);}349. else Beep();350.351. while(K1==0);352.353. do(354. if(PWM!=0xce)355. (PWM-- ;delayms(10);)356. else Beep();357.358. while(K2==0);359.360. }361.362. void timer0() interrupt 1363. (364. TR1=0;365. TH0=0xff ;366. TL0=0xce ;367. TH1=PWM ;368. TR1=1 ;369. P00=0 ; //启动输出370. } 371.372.373. void timer1() interrupt 3374. (375. TR1=0 ;376. P00=1 ; 〃结束输出377. }378.378. /*********************************************************/ 379. //蜂鸣器子程序380. /*********************************************************/ 382. 383. void Beep()384. (385. unsigned char i ;386. for (i=0 ;i<100 ;i++)387. {388. delay(100);389. BEEP=!BEEP ; //Beep 取反390. }391. BEEP=1 ; 〃关闭蜂鸣器392. delayms(100);393. }394.394. /*********************************************************/395. //延时子程序396. /*********************************************************/397. void delay(unsigned char t)398. {399. while(t--) ;401. } 402.403. /*********************************************************/404. //延时子程序405. /*********************************************************/406. void delayms(unsigned char ms)407.407. {408. unsigned char i ;409. while(ms--)410. {411. for(i = 0 ; i < 120 ; i++);412. }413. }415.414. /*********************************************************/415. #include < reg51.h >416. #include < intrins.h >419.420. sbit K1 =P1A4 ; //增加键421. sbit K2 =P"5 ; //减少键422. sbit P00 =P0A1;423. sbit BEEP =P3A7 ; //蜂鸣器424. unsigned char PWM=0xe7; // 赋初值425.425. void Beep();426. void delayms(unsigned char ms);427. void delay(unsigned char t);429.*****************************************************431. void main()432. (433.433. P1=0xff;434. TMOD=0x21 ;435. TH0=0xff ; //50us 延时常数436. TL0=0xce ; // 频率调节438.439. TH1=PWM ; //脉宽调节440. TL1=0 ;441.441. EA=1;442. ET0=1;443. ET1=1;445.444. TR0=1 ;447.445. while(1)450. do(451. if(PWM!=0xff)452. (PWM++ ;delayms(10);) 453. else Beep();454. }455. while(K1==0);456.456. do(457. if(PWM!=0xce)458. {PWM--;delayms(10);} 459. else Beep();460. }461. while(K2==0);462. }463. }465.464. void timer0() interrupt 1465. {466. TR1=0 ;467. TH0=0xff ;468. TL0=0xce ;469. TH1=PWM ;470. TR1=1 ;471. P00=0 ; 〃启动输出472. }475.476.473. void timer1() interrupt 3474. {475. TR1=0 ;476. P00=1 ; //结束输出482.483. /*********************************************************/484. //蜂鸣器子程序485. /*********************************************************/ 486.487. void Beep()488. {489. unsigned char i ;490. for (i=0 ;i<100 ;i++)491. {492. delay(100);493. BEEP=!BEEP ; //Beep 取反494. }495. BEEP=1 ; //关闭蜂鸣器496. delayms(100);497. }498.498. /*********************************************************/499. //延时子程序500. /*********************************************************/501. void delay(unsigned char t)502. {503. while(t--) ;505. } 506.507. /*********************************************************/508. //延时子程序509. /*********************************************************/510. void delayms(unsigned char ms) 511.512. {513.unsigned char i ; 514.while(ms--) 515.{ 516.for(i = 0 ; i < 120 ; i++); 517.}518. }519. 519. /*********************************************************/ 520. #include < reg51.h >521. #include < intrins.h >523.522. sbit K1 =P1A 4 ;〃增加键 523. sbit K2 =P"5 ;// 减少键 524. sbit P00 =P0A1;525. sbit BEEP =P3A7 ;// 蜂鸣器526. unsigned char PWM=0xe7; // 赋初值529.527. void Beep();528. void delayms(unsigned char ms);529. void delay(unsigned char t);533.534. /*********************************************************/536. { 537. 538. P1=0xff; 539. TMOD=0x21 540. TH0=0xff ; 541. TL0=0xce ; 542. 543.TH1=PWM ; 544. TL1=0 ; 535. void main() //50us 延时常数 //频率调节 //脉宽调节545.546. EA=1;547. ET0=1;548. ET1=1;549.549. TR0=1 ;551.550. while(1)551. {552. do{553. if(PWM!=0xff)554. {PWM++ ;delayms(10);} 555. else Beep();556. }557. while(K1==0);560.558. do{559. if(PWM!=0xce)560. {PWM--;delayms(10);} 561. else Beep();562. }563. while(K2==0);564. }565. }569.566. void timer0() interrupt 1567. {568. TR1=0 ;569. TH0=0xff ;570. TL0=0xce ;571. TH1=PWM ;572. TR1=1 ;578. } 579.580. 581. void timer1() interrupt 3582. {585. } 586.587. /*********************************************************/ 588. //蜂鸣器子程序 589./*********************************************************/ 590. 591. void Beep()592.595.delay(100)598.601.602.603. /*********************************************************/ 604. //延时子程序 605./*********************************************************/ 606. void delay(unsigned char t)607. {608. while(t--) ; 577. P00=0 ;//启动输出583.TR1=0; 584.P00=1 ; //结束输出593.unsigned char i 594.for (i=0 ;i<100 ;i++)596.597.BEEP=!BEEP ; //Beep 取反 599.BEEP=1 //关闭蜂鸣器 600.delayms(100);609. }610.610. /********************************************************* /611. //延时子程序612. /********************************************************* /613. void delayms(unsigned char ms)615.614. {615. unsigned char i ;616. while(ms--)617. {618. for(i = 0 ; i < 120 ; i++);619. }620. }623.624. /*********************************************************/。

STC单片机实现可调PWM输出的C51程序

STC单片机实现可调PWM输出的C51程序

STC单片机实现可调PWM输出的C51程序//以下是源程序,只需修改定义IO 口就可以使用,#include #include sbit K1 =P3 ; //增加键sbit K2 =P3; //减少键sbit BEEP =P3; //蜂鸣器sbit pp =P3;unsigned char PWM=0x7f ; //赋初值void Beep();void delayms(unsigned char ms);void delay(unsigned char t);/*********************************************************/voidmain(){ pp=1; TMOD=0x21 ; TH0=0xfc ; //1ms 延时常数TL0=0x66 ; //频率调节TH1=PWM ; //脉宽调节TL1=0 ; EA=1; ET0=1; ET1=1; TR0=1 ; while(1) { do{if(PWM!=0xff) {PWM++ ;delayms(10);} else Beep() ; } while(K1==0); do{if(PWM!=0x02) {PWM-- ;delayms(10);} else Beep() ; } while(K2==0);}}/*********************************************************/// 定时器0 中断服务程序./*********************************************************/void timer0()interrupt 1{ TR1=0 ; TH0=0xfc ; TL0=0x66 ; TH1=PWM ; TR1=1 ; pp=0 ; //启动输出}/*********************************************************/// 定时器1 中断服务程序/*********************************************************/void timer1()interrupt 3{ TR1=0 ; pp=1 ; //结束输出} /*********************************************************///蜂鸣器子程序/*********************************************************/voidBeep() { unsigned char i ; for (i=0 ;i<100 ;i++) { delay(100) ; BEEP=!BEEP ; //Beep取反} BEEP=1 ; //关闭蜂鸣器delayms(100); } /*********************************************************/// 延时子程序/*********************************************************/voiddelay(unsigned char t){ while(t--) ;}/*********************************************************/// 延时子程序/*********************************************************/voiddelayms(unsigned char ms){ unsigned char i ; while(ms--) { for(i = 0 ; i < 120 ; i++) ;}}tips:感谢大家的阅读,本文由我司收集整编。

单片机PWM控制LED灯渐亮渐灭C51程序

单片机PWM控制LED灯渐亮渐灭C51程序

想跟新人分享。
/***************************************************************************** 硬件说明:
AT89S52,晶振 11.0592MHz。P3.6 为一个 LED 背光板,等于 0 时发光。
P0.0 为一个按键,按下时为 0。
时 ZKB1=ZKB2,实现有暗变亮;当 100<ZKB2<=200 时 ZKB1=200-ZKB2,实现由亮变暗;当
200<ZKB2<=400 时 ZKB1=0,LED 保持熄灭。从时间上来说,每一个亮度等级耗时 10ms,那
么渐亮耗时 1s,渐灭耗时 1s,熄灭保持 2s,然后开始下一个周期。
这里我还加了一个 flag0 变量,作用是当 K0 按下时使 LED 停止发光。
LED3=0; else
LED3=1; if (ZKB2>399) ZKB2=1;
} else {
LED3=1; } } /*------------------------------主函数-------------------------------------*/
void main (void) { init_sys(); while(1) {
******************************************************************************/
#include <REG52.H>
#define uchar unsigned char #define V_TH0 0xff //定时器 0 初值
void Beep() { unsigned char i ; for (i=0 ;i<100 ;i++) { delay(100) ; BEEP=!BEEP ; } BEEP=1 ; delayms(100); }

c51单片机C语言编写的PWM程序

c51单片机C语言编写的PWM程序

89c51单片机C语言编写的P W M程序(共3页)-本页仅作为预览文档封面,使用时请删除本页-89c51单片机C语言编写的PWM程序PWM, 单片机, C语言, 程序, 编写分享到:新浪微博 QQ空间开心网人人网说明:本程序使用STC89C52RC单片机,晶振,要使用本程序需要自己修改,我是用来控制直流电机的,外接了L298驱动电路,有问题或意见请回复,谢谢^_^#include ""#include ""转;speed<0.反转(-100~100)调用:extern int abs(int val); 取绝对值返回:/******************************************************************/ void motor(char speed1,char speed2){ //==============左边电机============= if (speed1>0) { IN1 =0;IN2 =1;//正转} else if (speed1<0) { IN1 =1;IN2 =0;//反转}//==============右边电机============= if (speed2>0) { IN3 =1;IN4 =0;//正转} else if (speed2<0) { IN3 =0;IN4 =1;//反转}}/******************************************************************名称:motor_PWM();功能:PWM占空比输出参数:无调用:无返回:无/******************************************************************/void motor_PWM (){ uchar PWM_abs1; uchar PWM_abs2;PWM_abs1=MOTO_speed1; PWM_abs2=MOTO_speed2;if (PWM_abs1>PWMAnd) ENA=1; //左边电机占空比输出else ENA=0; if (PWM_abs2>PWMAnd) ENB=1; //右边电机占空比输出else ENB=0; if (PWMAnd>=PWM_COUST) PWMAnd=0; //PWM计数清零else PWMAnd+=1;}/******************************************************************名称:void TIME_Init ();功能:定时器初始化指令:调用:无返回:无/******************************************************************/void TIME_Init (){//=========定时器T2初始化 PWM==================T2CON = 0x00;T2MOD = 0x00;RCAP2H = 0xff; //定时RCAP2L = 0x47; TH2 = 0xff; TL2 = 0x47; ET2 = 1; //定时器2中断开TR2 = 1; //PWM定时器关,PWM周期为10ms }/******************************************************************名称:void PWM_Time2 () interrupt 5功能:T2中断,PWM控制参数:调用:motor_PWM();//PWM占空比输出返回:/******************************************************************/ void PWM_Time2 () interrupt 5{ TR2 = 0; TF2 = 0; ET2 = 0; //定时器0中断禁止motor_PWM();//PWM占空比输出ET2 = 1; //定时中断0开启TR2 = 1;}main(){TIME_Init () ;motor(50,50);//左右电机的转速都是50}。

STCMCU的软件和硬件PCAPWM输出

STCMCU的软件和硬件PCAPWM输出

STCMCU的软件和硬件PCAPWM输出软件⽅式输出PWMPWM⽤于输出强度的控制, 例如灯的亮度, 轮⼦速度等, STC89/90系列没有硬件PWM, 需要使⽤代码模拟使⽤纯循环的⽅式实现PWM⾮中断的实现(SDCC环境编译)#include <8052.h>#define Led10 P0_7typedef unsigned int u16;int atime = 64;// 仅作为延时, pms取值区间为 0 - 64void delay(u16 pms) {u16 x, y;for (x=pms; x>0; x--) {for (y=11; y>0; y--);}}// 这⾥控制占空⽐, i取值区间为 0 - 64,// i越⼤脉冲宽度越低, 因为输出是低位点亮, 所以i越⼤LED越亮void ledfade(u16 i) {Led10 = 0;delay(i);Led10 = 1;delay(atime-i);}int main(void) {u16 a, b;// 每个循环, ⼩灯while(1) {// a增⼤, 脉冲宽度降, 亮度增for (a=0; a<atime; a++) {for (b=0; b < (atime - a)/4; b++) {ledfade(a);}}// a减⼩, 脉冲宽度增, 亮度降for (a=atime; a>0; a--) {for (b=0; b < (atime - a)/4; b++) {ledfade(a);}}}}使⽤中断的⽅式因为需要PWM输出的场景, ⼀般都不会仅仅有PWM输出, 所以通常会做到定时器中断中, 由中断来实现将1和0的时间宽度设置为定时器, 直接做到定时器中断⾥⾯这个代码中1. pwm_flag代表了输出的0和1, 每次定时器中断时进⾏切换, 并设置下⼀次中断的时间宽度2. 缺点: ⽤TR0做开关, 但是这种停⽌⽅式, 停⽌后输出可能还是1/* Global variables and definition */#define PWMPIN P1_0unsigned char pwm_width;bit pwm_flag = 0;void pwm_setup(){TMOD = 0; // Timer mode 0, 13bitpwm_width = 160;EA = 1;ET0 = 1;TR0 = 1;}/* Timer 0 Interrupt service routine */void timer0() interrupt 1{if (!pwm_flag) { /* Start of High level */pwm_flag = 1; /* Set flag */PWMPIN = 1; /* Set PWM o/p pin */TH0 = pwm_width; /* Load timer */TF0 = 0; /* Clear interrupt flag */} else { /* Start of Low level */pwm_flag = 0; /* Clear flag */PWMPIN = 0; /* Clear PWM o/p pin */TH0 = 255 - pwm_width; /* Load timer */TF0 = 0; /* Clear Interrupt flag */}}void pwm_stop(){TR0 = 0; /* Disable timer to disable PWM */}使⽤定时器模式2和中断实现的PWM输出使⽤定时器⼯作模式2定时器通过对变量tt做计数, 与scale做⽐较, 确定是否翻转电压这⾥scale分10个等级, scale=1时占⽐1/10个PWM周期(250us * 10 = 2.5ms), 在主循环⾥改变scale因为是低电平点亮LED, 所以tt<=scale的时间LED是暗的, scale增⼤时亮度变⼩, 这个可以根据⾃⼰电路的情况调整这样存在的问题是修改scale的值时, 可能正好在tt计数范围的中间, 导致输出出现⽑刺, 可以通过增加⼀个中间变量来解决, 在tt计数时⽐较的是这个中间变量, 在周期结束时再⽤新值更新这个中间变量#include<reg51.h>sbit P10 = P1^0;sbit P11 = P1^1;unsigned int scale; //占空⽐控制变量void main(void) {unsigned int n; //延时循环变量TMOD = 0x02; //定时器0,⼯作模式2, 8位定时, TL0溢出时⾃动重载TH0中的值TH0 = 0x06; //定时, 250us⼀个中断 (12M晶振, 12分频后1MHz, 单次1us)TL0 = 0x06; //初始值TR0 = 1; //启动定时器0ET0 = 1; //启动定时器0中断EA = 1; //开启总中断while(1) {for(n = 0; n < 50000; n++); //延时50msscale++; //占空⽐控制, ⾃增if(scale == 10) scale = 0; //使占空⽐从0-10循环变化}}timer0() interrupt 1 {static unsigned int tt; //tt⽤来保存当前时间在⼀个时钟周期的位置tt++; //每中断⼀次,即每经过250us,tt的值⾃加1if (tt == 10) { //中断10次定时2.5mstt = 0; //使tt=0,开始新的周期,达到循环的效果P10 = 0; //点亮LED}if (tt <= scale) { //如果占空⽐与中断次数相同时,此时输出⾼电平P10 = 1; //熄灭LED灯}}使⽤定时器模式2和中断实现的多路PWM输出实现多路PWM输出的思路1. 使⽤⼀个基础定时器, 定时器时间不能太⼤, 例如设置为100us, 可以⽤定时器模式2, 这样初始值能⾃动重置2. 设定⼀个PWM周期, 这个周期就是定时器间隔的整数倍, 例如10倍定时器周期, 就是1000us = 1ms3. 对于每个PWM通道设置⼀个计数, 计数在达到PWM周期时置零, 这是实现PWM周期的基础设置⼀个初始输出, ⾼电平或低电平设置⼀个输出宽度, 计数达到这个宽度值时翻转. 这个宽度决定了输出翻转的时间, ⽤于控制占空⽐4. 因为每个指令的执⾏时间需要1-2个CPU周期, 所以当通道数增加后, 误差会增⼤代码例⼦: 这⾥⽤8个位指定4个轮⼦的PWM输出, 每个轮⼦两位是为了控制轮⼦的正反向#include <reg52.h>typedef unsigned int u16;typedef unsigned char u8;// Wheel 0sbit P1_0 = P1^0;sbit P1_1 = P1^1;// Wheel 1sbit P1_2 = P1^2;sbit P1_3 = P1^3;// Wheel 2sbit P1_4 = P1^4;sbit P1_5 = P1^5;// Wheel 3sbit P1_6 = P1^6;sbit P1_7 = P1^7;/*Duty Cycle = Toogle_P1_x / PWM_Period;*/u8 PWM_Period = 128; // PWM Period = N * Timer delay(100us), between 10 - 254 u8 Toggle_W0 = 0; // Toggle of Wheel 0u8 Dir_W0 = 0; // Direction, 0:P1_0=0,P1_1=PWM, 1:P1_1=0,P1_0=PWMu8 Toggle_W1 = 0; // Toggle of Wheel 1u8 Dir_W1 = 0; // Direction, 0:P1_2=0,P1_3=PWM, 1:P1_3=0,P1_2=PWMu8 Count_W0, Count_W1;void Time0_Init(void){TMOD = 0x02; // Mode 2, 8-bit and auto-reloadTH0 = 0x9C; // 0x9c = 156, timer of 100us (12MHz OSC)TL0 = 0x9C;ET0 = 1;EA = 1;TR0 = 1;EX0 = 1; EX1 = 1; // Enable external interrupt 0 and 1IT0 = 1; IT1 = 1; // Toggle = jump}void main(){Time0_Init();while(1);}void Timer0_IT() interrupt 1{// W0if(Count_W0 == Toggle_W0) {if (Dir_W0 == 0) { // P1_1=PWMP1_1 = 0;} else { // P1_0=PWMP1_0 = 0;}}if(Count_W0 == PWM_Period - 1) {Count_W0 = 0;if (Dir_W0 == 0) {P1_0 = 0;P1_1 = 1;} else {P1_0 = 1;P1_1 = 0;}} else {Count_W0++;}// W1if(Count_W1 == Toggle_W1) {if (Dir_W1 == 0) { // P1_3=PWMP1_3 = 0;} else { // P1_2=PWMP1_2 = 0;}}if(Count_W1 == PWM_Period - 1) {Count_W1 = 0;if (Dir_W1 == 0) {P1_2 = 0;P1_3 = 1;} else {P1_2 = 1;P1_3 = 0;}} else {Count_W1++;}}// W0 dir0->maxvoid W0_dir0(void){if (Dir_W0 == 0) {Toggle_W0++;if(Toggle_W0 > PWM_Period) { Toggle_W0 = PWM_Period; }} else {Toggle_W0--;if(Toggle_W0 == 0) {Dir_W0 = 0;}}}// W0 dir1->maxvoid W0_dir1(void){if (Dir_W0 == 0) {Toggle_W0--;if(Toggle_W0 == 0) {Dir_W0 = 1;}} else {Toggle_W0++;if(Toggle_W0 > PWM_Period) { Toggle_W0 = PWM_Period; }}}// W1 dir0->maxvoid W1_dir0(void){if (Dir_W1 == 0) {Toggle_W1++;if(Toggle_W1 > PWM_Period) { Toggle_W1 = PWM_Period; }} else {Toggle_W1--;if(Toggle_W1 == 0) {Dir_W1 = 0;}}}// W1 dir1->maxvoid W1_dir1(void){if (Dir_W1 == 0) {Toggle_W1--;if(Toggle_W1 == 0) {Dir_W1 = 1;}} else {Toggle_W1++;if(Toggle_W1 > PWM_Period) { Toggle_W1 = PWM_Period; }}}void IT0_INT() interrupt 0{W1_dir0();}void IT1_INT() interrupt 2{W1_dir1();}硬件PWM51系列单⽚机的增强型版本, 有些带PCA(Programmable Counter Array 可编程计数序列)模块, 可以通过PCA实现PWM的输出.PCA介绍PCA其实就是⼀个增强型的计数器, 这个计数器中的⼀些元素是可以在代码中设置的, 例如可以设置的计数脉冲源, 可以来⾃于系统时钟, 系统时钟可以是不分频, 2分频, 4分频, 6分频, 8分频等; 来⾃计数器; 来⾃外部输⼊的时钟可以设置计数的触发条件, 上升沿还是下降沿, 或者都计数. 最后这个计数⽅式, 可以⽤来计算脉宽可以设置16位的⽐较值不占⽤CPU资源, 这点很重要, 可以使输出更加精确和稳定因为上⼀点, 有些型号可以做到在CPU处于IDLE状态时继续计数(输出)可以⽤PCA实现PWM输出功能STC12C5A60S2系列PCA实现的PWM参考STC12C5A60S2的⼿册有两路输出, 默认PWM0:P1.3, PWM1:P1.4, 可以换到P4⼝: PWM0:P4.2, PWM1:P4.3这个在AUXR1⾥⾯控制两路共⽤PCA定时器, 定时器的频率由CMOD控制因为PWM输出是8位的, 所以定时器的频率/256就是PWM频率两路输出的占空⽐是独⽴变化的, 与当前的[EPCnL, CCAPnL]的值有关前者的值在 PCA_PWM0 PCA_PWM1 ⾥控制后者的值在 CCAP0L,CCAP0H 和 CCAP1L,CCAP1H ⾥控制先输出低, 当CL的值⼤于等于[EPCnL, CCAPnL]时, 输出为⾼当CL由FF变为00时, 输出变低, 同时⾃动将[EPCnH, CCAPnH]的值装载到[EPCnL, CCAPnL], 实现⽆⼲扰更新PWM占空⽐下⾯的代码中, CCAP1H 控制的就是装载值, CCAP1L 控制的是⽐较值, PCA_PWM1 控制的是EPCnH 和 EPCnL如果 EPCnL = 0, 那么正常输出如果 EPCnL = 1, 那么会⼀直输出低电平#include <STC12C5A60S2.H>void main() {CCON = 0; // Initial PCA control register// PCA timer stop running// Clear CF flag// Clear all module interrupt flagCL = 0; // Reset PCA base timerCH = 0;CMOD = 0x02; // Set PCA timer clock source as Fosc/2// Disable PCA timer overflow interruptCCAP0H = CCAP0L = 0x80; // PWM0 port output 50% duty cycle suquare waveCCAPM0 = 0x42; // PCA module-0 as 8-bit PWM, no PAC interruptCCAP1H = CCAP1L = 0xFF; // PWM1port output 0% duty cycle square wavePCA_PWM1 = 0x03; // PWM will keep low levelCCAPM1 = 0x42; // PCA module-0 as 8-bit PWM, no PAC interruptCR = 1; // PCA timer start runwhile(1);}对PCA_PWM1的说明;PCA_PWMn: 7 6 5 4 3 2 1 0; EBSn_1 EBSn_0 - - - - EPCnH EPCnL;B5-B2: 保留;B1(EPCnH): 在PWM模式下,与CCAPnH组成9位数。

51系列单片机输出PWM的两种方法

51系列单片机输出PWM的两种方法

51系列单片机输出PWM的两种方法51系列单片机(如STC89C52、AT89C51等)是一种常用的8位微处理器,具有较高的性价比和广泛的应用领域。

PWM(Pulse Width Modulation)是一种常用的模拟信号生成技术,在很多领域中都有广泛应用,比如电机控制、LED调光等。

在51系列单片机中,有两种常用的方法可以实现PWM输出,分别是软件实现PWM和硬件实现PWM。

下面将详细介绍这两种方法及其实现方式。

1.软件实现PWM软件实现PWM是通过定时器和IO口的相互配合来产生PWM信号。

具体实现的步骤如下:步骤1:设置定时器的工作模式和计数器初值。

选择一个合适的定时器,比如定时器0,然后设置定时器工作模式和计数器初值。

定时器的工作模式选择“模式1”或“模式2”,并根据需求设置计数器初值。

步骤2:设置IO口的工作模式。

选择一个合适的IO口,比如PWM输出口(如P1.2),然后将该IO口设置为输出模式。

步骤3:编写软件控制代码。

在主循环中,通过改变IO口的电平状态来实现PWM输出。

根据定时器的计数值,可以确定PWM信号的占空比大小。

当定时器计数值小于一些阈值时,将IO口置高电平;当定时器计数值大于该阈值时,将IO口置低电平。

通过改变该阈值,可以实现不同的PWM占空比。

通过上述步骤,就可以实现软件控制的PWM输出。

需要注意的是,软件实现PWM的精度较低,同时也会占用较多的处理器时间。

2.硬件实现PWM硬件实现PWM是通过专门的PWM模块或专用的计时电路来实现PWM输出。

具体实现的步骤如下:步骤1:选择一个合适的PWM模块或计时电路。

可以选择专门的PWM模块(如PCA模块)或计时电路(如555计时芯片),根据需求选择合适的硬件模块。

步骤2:设置PWM模块或计时电路的相关参数。

根据需求设置PWM频率、占空比等参数。

步骤3:连接并配置IO口。

将PWM模块或计时电路的输出引脚连接到需要输出PWM信号的IO口,然后将该IO口设置为输出模式。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
相关文档
最新文档