打印
[LOOK]

根据Lee老师建议修改LOOK_ADC_PWM(邮箱传递数据)

[复制链接]
2755|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
wang0225|  楼主 | 2011-8-24 09:08 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 wang0225 于 2011-8-24 10:03 编辑

LOOK_ADC_PWM.h
 
#ifndef __LOOK_ADC_PWM_H
#define __LOOK_ADC_PWM_H
#include "look_config.h"
#include <look.h>
// 任务类 task_LOOK_ADC_PWM_t 的定义
class task_LOOK_ADC_PWM_t : public task_t {
public:
__INLINE__ task_LOOK_ADC_PWM_t(); // 构造函数
bool send_message(int msg);
protected:
void routine();  // 任务例程
mbox_t<int>mbox;
};
// 任务类 LOOK_ADC_PWM 的构造函数
__INLINE__ task_LOOK_ADC_PWM_t::task_LOOK_ADC_PWM_t()
{
// TODO: 在此初始化 task_LOOK_ADC_PWM_t 的类成员
}

extern instantiate::task<task_LOOK_ADC_PWM_t, LOOK_STACK_SIZE> task_LOOK_ADC_PWM;
#endif // __LOOK_ADC_PWM_H

LOOK_ADC_PWM.cpp

/*
初始化设置:  时钟配置为 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的中断里通过邮箱把AD值传出去,因为邮箱不能传数据0,故在AD值上加上一基数10.
     按照老师的建议取消 PWM0_Duty_Cycle这个全局变量,在adc_t::isr()函数中,取消了一些与ADC无关的操作(计算PWM的占空比)。
     使用邮箱,在通知任务时,直接把数据作为同步对象的通信数据发出 。
     把 AD_Result封装在adc_t里。
           在此特别感谢Lee老师的帮助!
上传日期:   2011/8/24
*/
#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
class adc_t : public interrupt_t {
public:
__INLINE__ adc_t();
protected:
bool isr(int vector);
void dsr(int vector, uintptr_t count);
private:
     uint32_t AD_Result;
};
// 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
  AD_Result = ADCs.ADDR1.Regs&0xFFF;
//PWM0_Duty_Cycle=AD_Result/50;
#else
ADC.ADSR().ADF = 1;    // 清中断 flag
  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
{
  task_LOOK_ADC_PWM.send_message(AD_Result+10);
}
}
adc_t adc;         // 创建adc对象
// 任务类 task_LOOK_PWM_t 的例程
void task_LOOK_ADC_PWM_t::routine()
{
// TODO: 在此编写 task_LOOK_PWM_t 例程的内容
uint8_t PWM0_Duty_Cycle = 50;   //PWM初始化占空比为50
#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 msg = mbox.get(); // 等待邮箱消息
   if (msg){
   msg-=10;
   if(msg<=0) msg=0;
   PWM0_Duty_Cycle=msg/50;   
   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 msg = mbox.get(); // 等待邮箱消息
   if (msg){
   msg-=10;
   if(msg<=0) msg=0;
   PWM0_Duty_Cycle=msg/50;
   if (PWM0_Duty_Cycle!=0)
     PWMA.CMR0 = u16Duty*PWM0_Duty_Cycle/100-1;  //更新占空比
    else PWMA.CMR0 = 0;
    }
}
#endif
}
bool task_LOOK_ADC_PWM_t::send_message(int msg)
{
    return mbox.do_tryput(msg);
}
  
#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
再次感谢Lee老师的帮助!

LOOK_ADC_PWM (邮箱).rar

2.66 MB

相关帖子

沙发
wang0225|  楼主 | 2011-8-24 09:27 | 只看该作者
经过我实践,可以把task_LOOK_ADC_PWM.send_message(AD_Result+10);
和bool task_LOOK_ADC_PWM_t::send_message(int msg)合成一个函数,即直接通过邮箱发送数据。

使用特权

评论回复
板凳
hotpower| | 2011-8-24 10:10 | 只看该作者
加偏移在这个例程中是不错的,但总归0是个问题。

使用特权

评论回复
地板
wang0225|  楼主 | 2011-8-24 10:11 | 只看该作者
是的,大叔!

使用特权

评论回复
5
wang0225|  楼主 | 2011-8-24 10:39 | 只看该作者
本帖最后由 wang0225 于 2011-8-24 10:42 编辑

mbox中,存储消息只用了一个32bits的数据,但还有一个关键的状态需要表示,就是mbox中是否有消息,对于此状态的表示方法,有两种设计策略:
1、在mbox中再加一个数据来表示。
2、将32bits数据,隔离出一个特殊值来表示。32bits数据的值域将少一个。
LOOK使用了第2种方法。
以上是对于存储的影响,对于API的影响有:
如果有特殊值(0),那么get()的返回值可以用0表示超时等失败的返回。如果是全值域,那么get()就必须返回两个数据,一个表示是否成功,一个表示数据本身。
全值域的get()可能的形式就是这样的:bool get(T& data);
而特殊值的get(),目前就是:T get();
特殊值的设计,不管是存储还是实现代码,开销都要比全值域的设计小些。
以上是Lee老师关于邮箱的一些说明,希望对大家有用!:)

使用特权

评论回复
6
mbydyjj| | 2011-9-30 10:42 | 只看该作者
看看

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

0

主题

185

帖子

1

粉丝