本帖最后由 wang0225 于 2011-8-22 21:44 编辑
/*
初始化设置: 时钟配置为 XTL12M_EN
CPU时钟频率为12MHz
外设时钟配置为PWM01_S : 外部 4~24MHz 晶振使能
外设时钟配置为PWM01_EN : 选上
外设时钟配置为ADC_S : 外部 4~24MHz 晶振使能
外设时钟配置为ADC_N : 3
外设时钟配置为ADC_EN : 选上
PA.1选择多功能管脚选择ADC1,输入
PA.12选择多功能管脚选择PWM0,输出
主要完成功能:产生400Hz的波形,刚开始的占空比会根据助学板上的电位器的情况而定。
旋转电位器可以改变PWM的占空比。
在AD的中断里发送sem实现PWM同步
在此特别感谢Lee老师的帮助!
上传日期: 2011/8/22
*/
#include "LOOK_ADC_PWM.h"
#define LOOK_H 1
#if LOOK_H == 0
#include "NUC1xx.h"
#include "NUC1xxM051Seriescfg.h"
#else
#include <nuc120re3an.h>
using namespace nuvoton;
#endif
//flag_t flag(0);
uint8_t PWM0_Duty_Cycle = 50; //PWM初始化占空比为50
class adc_t : public interrupt_t {
public:
__INLINE__ adc_t();
protected:
bool isr(int vector);
void dsr(int vector, uintptr_t count);
};
// adc_t 构造函数
__INLINE__ adc_t::adc_t()
{
attach(ADC_IRQn);
vector_t::enable(ADC_IRQn);
#if LOOK_H == 0
SYSs.IPRSTC2.Bits.ADC_RST = 1;
SYSs.IPRSTC2.Bits.ADC_RST = 0; /* Reset ADC */
//ADC时钟、分频及配置为AD引脚在look中配置
ADCs.ADCR.Bits.ADEN = 1; //使能AD模块
ADCs.ADCALR.Bits.CALEN = 1; //自校正使能
while(!ADCs.ADCALR.Bits.CALDONE); //等待自校正结束
ADCs.ADCR.Bits.DIFFEN = 0; //单端输入
ADCs.ADCR.Bits.ADST = 0; //停止AD
ADCs.ADCR.Bits.ADMD = 0; //单一转换
ADCs.ADCHER.Bits.CHEN = 0x02; //模拟输入通道1使能
ADCs.ADSR.Bits.ADF = 1; //清AD中断标志
ADCs.ADCR.Bits.ADIE=1; // 开启中断
#else
SYS.IPRSTC2().ADC_RST = 1;
SYS.IPRSTC2().ADC_RST = 0; // Reset ADC
//ADC时钟、分频及配置为AD引脚在look中配置
ADC.ADCR().ADEN = 1; //使能AD模块
ADC.ADCALR().CALEN = 1; //自校正使能
while(!ADC.ADCALR().CALDONE); //等待自校正结束
ADC.ADCR()
.DIFFEN(0) //单端输入
.ADST(0) //停止AD
.ADMD(0); //单一转换
ADC.ADCHER().CHEN = 0x02; //模拟输入通道1使能
ADC.ADSR().ADF = 1; //清AD中断标志
ADC.ADCR().ADIE = 1; // 开启中断
#endif
}
// adc_t 中断服务例程
bool adc_t::isr(int vector)
{
#if LOOK_H == 0
ADCs.ADSR.Bits.ADF = 1; // 清中断 flag
uint32_t AD_Result = ADCs.ADDR1.Regs&0xFFF;
PWM0_Duty_Cycle=AD_Result/50;
#else
ADC.ADSR().ADF = 1; // 清中断 flag
uint32_t AD_Result = ADC.ADDR1&0xFFF;
PWM0_Duty_Cycle=AD_Result/50;
#endif
return true;
}
// adc_t 中断滞后服务例程
void adc_t::dsr(int vector, uintptr_t count)
{
if (vector == ADC_IRQn)//ADC1
{
// flag.do_set_bits(0b001);
task_LOOK_ADC_PWM.sem.do_post();
}
}
adc_t adc; // 创建adc对象
// 任务类 task_LOOK_PWM_t 的例程
void task_LOOK_ADC_PWM_t::routine()
{
// TODO: 在此编写 task_LOOK_PWM_t 例程的内容
#if LOOK_H == 0
SYSCLKs.CLKSEL1.Bits.TMR0_S = 0b000; //外部12M晶振
PWM0s.PCR.Bits.CH0INV = 0; //反向关闭
PWM0s.PCR.Bits.CH0MOD = 1; //自动重载
PWM0s.PPR.Bits.CP01 = 1; //预分频 1
PWM0s.CSR.Bits.CSR0 = 0b100; //分频系数 1
uint16_t u16Duty = 12000000/((1+1)*1*400);//PWM 频率 400HZ
PWM0s.CNR0.Regs = u16Duty-1; //PWM 频率 = PWMxy_CLK/(prescale+1)*(clock divider)/(CNR+1);
PWM0s.CMR0.Regs = u16Duty*PWM0_Duty_Cycle/100-1; //占空比 = (CMR+1)/(CNR+1).
PWM0s.POE.Bits.PWM0 = 1; //PWM0输出使能
//PA.12作为PWM0 使用LOOK进行配置
PWM0s.PCR.Bits.CH0EN = 1; // 使能PWM功能
while (true)
{
// TODO: 在此编写 task_ad_t 例程的内容
ADCs.ADCR.Bits.ADST = 1; //启动AD
// int 标志寄存器 = flag.wait(0b001, flag_t::ANY_CONSUME);
if (sem.wait()){
// PWM0s.CMR0.Regs = u16Duty*PWM0_Duty_Cycle/100-1; //更新占空比
if (PWM0_Duty_Cycle!=0)
PWM0s.CMR0.Regs = u16Duty*PWM0_Duty_Cycle/100-1; //更新占空比
else PWM0s.CMR0.Regs = 0;
}
}
#else
SYSCLK.CLKSEL1().TMR0_S = tmrs_t::XTL12M; //外部12M晶振
PWMA.PCR()
.CH0INV(0) //反向关闭
.CH0MOD(1); //自动重载
PWMA.PPR().CP01 = 1; //预分频 1
PWMA.CSR().CSR0 = 0b100; //分频系数 1
uint16_t u16Duty = 12000000/((1+1)*1*400);//PWM 频率 400HZ
PWMA.CNR0 = u16Duty-1; //PWM 频率 = PWMxy_CLK/(prescale+1)*(clock divider)/(CNR+1);
PWMA.CMR0 = u16Duty*PWM0_Duty_Cycle/100-1; //占空比 = (CMR+1)/(CNR+1).
PWMA.POE().PWM0 = 1; //PWM0输出使能
//PA.12作为PWM0 使用LOOK进行配置
PWMA.PCR().CH0EN = 1; // 使能PWM功能
while (true)
{
// TODO: 在此编写 task_ad_t 例程的内容
ADC.ADCR().ADST = 1; //启动AD
// int 标志寄存器 = flag.wait(0b001, flag_t::ANY_CONSUME);
if (sem.wait()){
// PWMA.CMR0 = u16Duty*PWM0_Duty_Cycle/100-1; //更新占空比
if (PWM0_Duty_Cycle!=0)
PWMA.CMR0 = u16Duty*PWM0_Duty_Cycle/100-1; //更新占空比
else PWMA.CMR0 = 0;
}
}
#endif
}
#ifdef LOOK_SCHEDULING_PRIORITY
instantiate::task<task_LOOK_ADC_PWM_t, LOOK_STACK_SIZE> task_LOOK_ADC_PWM(0);
#else
instantiate::task<task_LOOK_ADC_PWM_t, LOOK_STACK_SIZE> task_LOOK_ADC_PWM;
#endif
照片参考LOOK_ADC_PWM0。再次感谢Lee老师的帮助! |