A. STC單片機PWM編程!
看看這個,單片機用的是,AD轉換輸出正弦波,和PWM原理類似。
2、源程序清單
DACCONEQU0xfD;定義模數轉換控制器
DACHEQU0xfc;定義模數轉換數據寄存器高8位
DACLEQU0xfb;定義模數轉換數據寄存器低8位
ORG0000H
LJMPMAIN
ORG0200H
MAIN:MOVDACCON,#0fH;DACoperation
CLRA;
MOVDACH,A;模數轉換高八位清零
PRG3:MOVR0,#09H;正弦波
MOVR4,#40H
LP11:MOVA,R0
MOVCA,@A+PC
MOVDACL,A;2
ACALLDELAY;2
INCR0;1
DJNZR4,LP11;2
SJMPPRG3;2
DATA0:
DB80H,8CH,98H,0A5H,0B0H,0BCH,0C7H,0D1H,0DAH,0E2H,0EAH
DB0F0H,0F6H,0FAH,0FDH,0FFH,0FFH,0FDH,0FAH,0F6H,0F0H
DB0EAH,0E2H,0DAH,0D1H,0C7H,0BCH,0B0H,0A5H,98H,8CH
DB80H,7FH,73H,67H,5AH,4FH,43H,38H,2EH,25H,1DH,15H
DB0FH,09H,05H,02H,00H,00H,02H,05H,09H,0FH,15H
DB1DH,25H,2EH,38H,43H,4FH,5AH,67H,73H,7FH
RET
DELAY:MOVR6,#10H
MOVR7,#0A1H
DELAYLOOP:;延時程序
DJNZR6,DELAYLOOP
DJNZR7,DELAYLOOP
RET
四、實驗板插針配置:
無需插針配置,注意DAC是從CONDACOUT1端子輸出,可用示波器觀察DAC輸出波形。若產生失真情況,請檢查開發板DA輸出端LM358運算放大器的放大倍數,適當更改所查函數表的范圍。
五、思考題
1、改變程序,使能添加輸出鋸齒波;
2、改變程序,使輸出添加三角波;
3、改變程序,使輸出添加方波;
4、改變程序,並製作一個簡單的函數發生器
B. 請問:單片機使用C語言編程,怎樣控制led燈的完成亮度強弱變換
你可以使用ad轉換 或者直接控制脈沖頻率
C. 求一單片機程序(用光敏電阻,PWM輸出控制LED亮度)
ORG 0000H
L0000: LJMP MIN00 ; 主程序
; / *** *** *** *** / 初始化 PWM
PCA00: MOV CMOD, #82H ; (fSYS/2)
MOV CCON, #00H
MOV CL, #00H
MOV CH, #00H
MOV CCAPM0, #00H ; PWM0 輸出
MOV PCA_PWM0, #00H
SETB CR ; 開 PWM
RET
; / *** *** *** *** / 主程序
P1M0 EQU 91H
P1M1 EQU 92H
P3M0 EQU 0B1H
P3M1 EQU 0B2H
ADC_CONTR EQU 0C5H ; A/D 轉換寄存器
ADC_DATA EQU 0C6H ; A/D 結果寄存器
MIN00: MOV P1M0, #08H ; 設置 P1.3 為高阻狀態
MOV P1M1, #08H
MOV ADC_CONTR, #0E3H ; 開A/D 轉換電源 P1.3
LCALL PCA00 ; 初始化 PWM
MIN10: NOP ; 主程序 入口
LCALL ADC00 ; 測光敏電阻電壓
MOV CCAP0H, A ; 寫入PWM 控制 發光亮度
LJMP MIN10
RET
; / *** *** *** *** / A/D 轉換通道 測電壓
ADC00: MOV ADC_DATA, #00H
ORL ADC_CONTR, #08H ; 啟動 AD 轉換
MOV A, #10H ; 判斷 AD 轉換是否完成
ANL A, ADC_CONTR
JZ ADC32 ; AD 轉換尚未完成, 繼續等待
ANL ADC_CONTR, #0E7H ; 清0 ADC_FLAG, ADC_START 位, 停止A/D 轉換
MOV A, ADC_DATA ; A = AD 轉換結果
RET
END
D. 單片機C語言PWM的典型程序謝謝
/ 利用定時器控制產生占空比可變的 PWM 波
// 按K1,PWM值增加,則占空比減小,電機減速。
// 按K2,PWM值減小,則占空比增加,電機加速。
// 當PWM值增加到最大值或減小到最小值時,蜂鳴器將報警。
/*********************************************************/
#include<reg51.h>
#include<intrins.h>
sbit K1 =P1^4 ; //PWM值增加鍵
sbit K2 =P1^5 ; //PWM值減少鍵
sbit BEEP =P3^7 ; //蜂鳴器
unsigned char PWM=0x7f ; //賦初值
void Beep();
void delayms(unsigned char ms);
void delay(unsigned char t);
/*********************************************************/
void main()
{
P1=0xff;
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 ;
P0=0x00 ; //啟動輸出
}
/*********************************************************/
// 定時器1中斷服務程序 (脈寬)
/*********************************************************/
void timer1() interrupt 3
{
TR1=0 ;
P0=0xff ; //結束輸出
}
/*********************************************************/
//蜂鳴器子程序
/*********************************************************/
void Beep()
{
unsigned char i ;
for (i=0 ;i<100 ;i++)
{
delay(100) ;
BEEP=!BEEP ; //Beep取反
}
BEEP=1 ; //關閉蜂鳴器
delayms(100);
}
/*********************************************************/
// 延時子程序
/*********************************************************/
void delay(unsigned char t)
{
while(t--) ;
}
/*********************************************************/
// 延時子程序
/*********************************************************/
void delayms(unsigned char ms)
{
unsigned char i ;
while(ms--)
{
for(i = 0 ; i < 120 ; i++) ;
}
}
/*********************************************************/
E. 請教51單片機利用PWM控制燈的亮度的程序
第一,要理解中斷在這里的作用是固定的「一小段」時間進入一次。
第二,專PWM_ON在程序中的作用很大,它會屬由0------>CYCLE------>0並且一直循環下去。可以把它看成一個有規律的變化的量。
第三,每進入中斷一次count++,滿足條件count==PWM_ON或count==CYCLE時改變LED的當前狀態。作用是給小燈亮或滅的時間不同。
第四,LED的亮度與其通電時間有關,也可以說成是占空比。上面的條件要理解成是呈線性增加或減小的頻率。可以理解成三角波,對應的面積就是通電時間。
不知能不能給你講明白!
F. 51單片機如何用一個按鍵和一個定時器來模擬PWM控制一個LED燈的亮度
使用定時器T0產生PWM方波,
用按鍵調整占空比,20級可調
控制led燈的亮度等級.
#include "my51.h"
#include "timer0.h"
#define grading 20 //亮度20級變化
sbit keyS3=P3^5; //按鍵調整占空比,PWM_keyChange++
sbit keyS4=P3^6; // PWM_keyChange--
u8 PWM_keyChange=10; //初值,按鍵調整在1~20之間變化
//占空比 PWM_keyChange/grading
void T0_work() //本函數由T0定時器中斷函數調用
{
if(timeMultiple1Flag)
{
led=off(7); //關閉7號燈
timeMultiple1Flag=0; //清定時器復用置位標志
}
if(timeMultiple2Flag)
{
led=on(7); //打開7號燈
timeMultiple2Flag=0; //清定時器復用置位標志
}
}
void main() //測試
{
u8 keyFlag=1; //程序中沒有消抖處理,只是簡易的按鍵進出自鎖標志
led0=ledon; //先打開0號燈,用於和7號燈對比亮度
initT0(1,10,grading); //1毫秒的基本定時,亮的時間1*10毫秒,暗1*(grading-10)毫秒
while(1)
{
if(0==keyS3)
{
if(keyFlag) //防止一次按鍵中多次執行
{
keyFlag=0; //清標志,類似同步鎖
if(++PWM_keyChange>grading)
{
PWM_keyChange=grading; //占空比最大100%
}
initT0(1,PWM_keyChange,grading);
}
}
else if(0==keyS4)
{
if(keyFlag)
{
keyFlag=0;
if(0==--PWM_keyChange) //占空比減小
{
PWM_keyChange=1; //最小占空比 1/20
}
initT0(1,PWM_keyChange,grading); //占空比減小
}
}
else
{
keyFlag=1; //按鍵鎖釋放標志,下一次按鍵時允許調整占空比
}
}
}
C代碼
#ifndef _MY51_H
#define _MY51_H
#include <reg52.h>
//#include <math.h>
#include <intrins.h>
#include <stdio.h>
#include "mytype.h"
#ifndef _51LED_
#define _51LED_
#define led P1 //P1匯流排連8個led燈,燈連573鎖存器,P1置低電平點亮
#define LED led
#define ON(x) P1&(~(1<<(x))) //打開某個燈,開多個燈用 ON(m) & ON(n)
#define OFF(x) P1|(1<<(x)) //關閉某個燈,關多個燈用 OFF(m)| OFF(n)
#define on(x) ON(x) //包含大小寫
#define off(x) OFF(x)
#define ledon 0 //某個燈,打開
#define ledoff 1 //某個燈,關閉
sbit led0=P1^0;
sbit led1=P1^1;
sbit led2=P1^2;
sbit led3=P1^3;
sbit led4=P1^4;
sbit led5=P1^5;
sbit led6=P1^6;
sbit led7=P1^7;
sbit ledLock=P2^5; //鎖定當前8個led的狀態,0鎖定 ,1不鎖定
#endif
/*************二進制輸入宏****************************/
#ifndef _LongToBin_
#define LongToBin(n) \
( \
((n >> 21) & 0x80) | \
((n >> 18) & 0x40) | \
((n >> 15) & 0x20) | \
((n >> 12) & 0x10) | \
((n >> 9) & 0x08) | \
((n >> 6) & 0x04) | \
((n >> 3) & 0x02) | \
((n ) & 0x01) \
)
#define bin(n) LongToBin(0x##n##l)
#define BIN(n) bin(n)
#define B(n) bin(n)
#define b(n) bin(n)
#endif
/*************單個數據位的置位宏*********************/
#ifndef _BIT_
#define BIT(n) (1<<n)
#define bit(n) BIT(n)
#endif
#define high 1 //高電平
#define low 0 //低電平
sbit beep=P2^3; //蜂鳴器
extern void delayms(u16 ms);
extern void delayXus(u8 us); //函數執行(8+6x)個機器周期, 即t=(8+6x)*1.085
/////////////////////////////////////////////////////////////////////////////
#endif
C代碼
#ifndef _TIMER0_H
#define _TIMER0_H
#include "my51.h"
extern u8 timeMultiple1Flag; //中斷時間復用置位標志,須手動清零
extern u8 timeMultiple2Flag; //中斷時間復用置位標志,須手動清零
extern void T0_work(); //該函數未實現,需外部實現
extern void initT0(u8 ms,u16 t_multiple1,u16 t_multiple2) ; //定時器初始化
#endif
C代碼
#include "timer0.h"
u8 TH0Cout=0 ; //初值
u8 TL0Cout=0 ;
u16 T0IntCouts1=0; //中斷計數
u16 T0IntCouts2=0; //中斷計數
u16 timeMultiple1=0; //中斷復用時間的倍數
u16 timeMultiple2=0; //中斷復用時間的倍數
u8 timeMultiple1Flag=0; //中斷時間復用置位標志,須手動清零
u8 timeMultiple2Flag=0; //中斷時間復用置位標志,須手動清零
//開啟定時器,定時完成後需要手動關閉TR0,否則將循環定時
//參數一是定時的毫秒數,參數二和三是定時基時的倍率數(定時復用)
void initT0(u8 ms,u16 t_multiple1,u16 t_multiple2) //定時器初始化設定,ms取值不超過65
{
u16 N=11059.2*ms/12; //定時器總計數值
TR0=STOP; //停掉定時器
ET0=CLOSE; //關定時器中斷
//對於110592晶振,ms為5的整數倍時沒有計算誤差,但ms最大不超過71毫秒
TH0Cout =(65536-N)/256; //裝入計時值零頭計數初值
TL0Cout =(65536-N)%256;
if(0==t_multiple1) //0倍的基準時間是不合理的,至少1倍
{
t_multiple1=1;
}
if(0==t_multiple2) //0倍的基準時間是不合理的,至少1倍
{
t_multiple2=1;
}
timeMultiple1=t_multiple1; //倍時
timeMultiple2=t_multiple2; //倍時
TMOD &= 0xf0; //清定時器0配置
TMOD |= 0x01; //配置定時器0的工作方式為1
EA =OPEN; //打開總中斷
ET0=OPEN; //打開定時器中斷
TH0=TH0Cout; //定時器裝入初值
TL0=TL0Cout;
TR0=START; //啟動定時器
}
void T0_times() interrupt 1 //T0定時器中斷函數
{
TH0=TH0Cout; //重裝初值
TL0=TL0Cout;
if(++T0IntCouts1==timeMultiple1) //判斷是否復用定時器
{
T0IntCouts1=0; //中斷次數清零,重新計時
timeMultiple1Flag=1; //復用定時器標志,須在T0_work()中手動清零
}
if(++T0IntCouts2==timeMultiple2) //判斷是否復用定時器
{
T0IntCouts1=0; //這個也要清,防止到達最小公倍數時亂掉
T0IntCouts2=0; //中斷次數清零,重新計時
timeMultiple2Flag=1; //復用定時器標志,須在T0_work()中手動清零
}
T0_work(); //調用工作函數
}