打印
[Cortex-M0技术交流]

RyanHsiung学习第二贴,0耗时 多路AD采集!

[复制链接]
2647|9
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 Ryanhsiung 于 2011-10-14 09:46 编辑

功能说明:    1、100ms 轮循 采集 片内温度、热敏电阻、可调电阻 3路AD
                        若去采集时没有转换完成,则跳出不采集。到下一个采集周期在采集,从而不必等待AD转换,以实现0耗时
                   2、每隔1S返回一次数据
程序说明:
   1、本程序继承于我的 0耗时按键,先前按键程序保留着
   2、AD采集结果没有进行过滤,结果使用8位整型保存
   3、热敏电阻阻值与温度的关系是非线性的,我将10-40度近似看做线性,用公式来求温度
        变换的公式我没有验证,若网友要引用请先验证后引用
      
关键代码如下:
int main (void)
{       
        User_SystemInit();                                        //初始化
        while(1)
        {
                ClrWDT();                                                 //喂狗
                ADC_SerialOutMessage();                        //输出AD信息,由systick驱动       
               
        }
}


系统滴答:
ivoid SysTick_Handler(void)
{
        static uint8_t count = 0;
        static uint8_t s_count = 0;
        SysTic_ClearIF();                                //向SYST_CSR.COUNTFLAG中写1 以清除标志

    Button_Check();                                        //BUTTON检测
        if(        count++ >= 10 )
        {
                count = 0;
                ADC_CollectTemp();                        //AD检测
        }
        if(s_count++ >= 100  )
        {
                s_count = 0;
                Flag_OneSecondForADC  = 1         ;                   //用于驱动AD信息输出        }
}


下面是AD程序
#include        "includes.h"
//特别说明 :本程序 底层是从lixiaoxu2meng那借鉴来的
static uint8_t ADC_CollectValue[ADC_CHANNEL_MAX_NUM];                        //存放采集值
static ADC_Channel_Type ADC_Channel;                                                        //选择通道
/*************************************************************************************
** Function name:       ADC_Configuration
** Descriptions:        ADC配置
** input parameters:    none
** output parameters:   none
** Returned value:      none
*************************************************************************************/
void ADC_Configuration(void)
{
        // ADC_SINGLE_END AD为单端输入模式
        // ADC_CONTINUOUS_OP 使用连续转换,若用单次采集则在采集完后必须重新打开采集                        //  ADC_SINGLE_OP 单一转换
        // 821 GA7 GA1 AG0作为输入 模式输入通道使能         ,/以下函数会改变ADCHER.CHEN的值,所以后面ADCHER.CHEN都被注释掉了
        // EXTERNAL_12MHZ ADC时钟为 外部12MHZ
        // 11 AD时钟频率 = ADC时钟/(11+1) = 1MHZ
        DrvADC_Open(ADC_SINGLE_END, ADC_CONTINUOUS_OP, 0x80|0x02|0x01, EXTERNAL_12MHZ, 11);            //DrvADC_SetADCChannel(0x80|0x02|0x01,ADC_SINGLE_END);       
        ADC->ADCR.ADIE = 0;                                                                                                        //关闭AD转换中断                                                                                                                                               
        ADC->ADCR.DMOF = 0;                                                                                                 //转化结果无符号
               
        //使能片内温度AD通道
        SYS->TEMPCR = 0x01;                                                                                                 //使能温度传感器
        //ADC->ADCHER.CHEN |= 0x80;                                                                                 //模拟输入通道7使能            CHEN7 =1 ;
        ADC->ADCHER.PRESEL = 0x02;                                                                                         //内部温度传感器
        //使能热敏电阻AD通道
        ///ADC->ADCHER.CHEN |= 0x01;                                                                                 //模拟输入通道0使能            CHEN0 =1 ;
        //使能可调电阻AD通道
        ///ADC->ADCHER.CHEN |= 0x01;                                                                                 //模拟输入通道1使能            CHEN1 =1 ;
         DrvADC_StartConvert();                                                                                         // 开启ADC转换         连续采集
}

/*************************************************************************************
** Function name:       ADC_Variable_Init
** Descriptions:        ADC变量初始化
** input parameters:    none
** output parameters:   none
** Returned value:      none
*************************************************************************************/
void ADC_Variable_Init(void)
{
        uint8_t i;
        //暂无 若无变量初始化,该函数可省略
        ADC_Channel =  E_ADC_Channel_Chip_Temp;
        for(i=0;i<ADC_CHANNEL_MAX_NUM;i++)
        {
                ADC_CollectValue[i] =0;
        }
}
/*************************************************************************************
** Function name:       ADC_Init
** Descriptions:        ADC初始化
** input parameters:    none
** output parameters:   none
** Returned value:      none
*************************************************************************************/
void ADC_Init(void)
{
        ADC_Configuration();
        ADC_Variable_Init();                        
        printf("ADC 初始完成!!\n");
}
/*************************************************************************************
** Function name:       ADC_CollectTemp
** Descriptions:        采集温度
** input parameters:    none
** output parameters:   none
** Returned value:      none
** Remark;                                AD采样很快,但是我每隔100MS才取一次
*************************************************************************************/
void ADC_CollectTemp(void)
{        //若用单次采集则在采集完后必须重新打开采集
        int32_t AD_Value;                                                                                        //用于存放AD值临时值                                                                  
        if(DrvADC_IsConversionDone()==TRUE);                                                 // 判断ADC是否转换结束
        { //不用等待,这里是0耗时的重点
                switch(ADC_Channel)
                {
                        case E_ADC_Channel_Chip_Temp:         // 芯片温度
                        {       
                                AD_Value = DrvADC_GetConversionData(7);                         //        取7通道,CHIP TEMP
                                AD_Value = AD_Value*3300/4095-730;                                         //         还需经过校正,现是套用他人的校正因子
                                AD_Value = AD_Value/-2;
                                ADC_CollectValue[ADC_Channel] = (uint8_t)AD_Value;
                                ADC_Channel = E_ADC_Channel_R_Temp;                                        //选择一下个通道
                        }break;
                        case E_ADC_Channel_R_Temp:            // 热敏电阻
                        {        //这个热敏电阻是非线性的,所以换算比较难做,最好用查表
                                //我这里将10 - 40度近似看作为线性,中间的温度偏差可以有好几度。
                                //由于这个热敏电阻无太大意义,故方程我没有验证,请广大网友不要随意应用,若要用请验证!
                                AD_Value = DrvADC_GetConversionData(0);                                                                 //        取0通道,AD
                                AD_Value = ((((float)AD_Value)/4096)*-135)*((float)3300 /4095) + 85 ;         //         还需经过校正
                                ADC_CollectValue[ADC_Channel] = (uint8_t)AD_Value;                  
                                ADC_Channel = E_ADC_Channel_Resister;                                //选择一下个通道
                        }break;
                        case E_ADC_Channel_Resister:        // 可调电阻
                        {                                                                  
                                AD_Value = DrvADC_GetConversionData(1);                         //        取1通道,AD
                                AD_Value = AD_Value*3300/4095;                                                //         还需经过校正
                                AD_Value = 100*((float)(3300 - AD_Value)/3300);
                                ADC_CollectValue[ADC_Channel] = (uint8_t)AD_Value;           
                                ADC_Channel = E_ADC_Channel_Chip_Temp;                                //选择一下个通道
                        }break;
                        default:break;
                }
        }
}
/*************************************************************************************
** Function name:       ADC_SerialOutMessage
** Descriptions:        通过时间事件驱动,每隔1S通过串口发送一次数据给上位机
** input parameters:    none
** output parameters:   none
** Returned value:      none
*************************************************************************************/
void ADC_SerialOutMessage(void)
{
        if(Flag_OneSecondForADC)
        {
                Flag_OneSecondForADC =0;
                printf("芯片温度:%d C   热阻温度: %d C  电阻阻值: %d(0.1kΩ) \n",\
                                ADC_CollectValue[0],ADC_CollectValue[1],ADC_CollectValue[2]);
        }
}
                                 

温度采集.png (7.46 KB )

温度采集.png

ADC For RyanHsiung Study.rar

1.33 MB

相关帖子

沙发
Ryanhsiung|  楼主 | 2011-10-14 09:48 | 只看该作者
上面太长了,ADC.H内容,主要是定义了一个枚举类型
#ifndef        __ADC_H
#define        __ADC_H
#include "Driver\DrvADC.h"
#define ADC_CHANNEL_MAX_NUM                        3       
typedef enum  type_ADC_Channel
{
        E_ADC_Channel_Chip_Temp = 0,
        E_ADC_Channel_R_Temp = 1,
        E_ADC_Channel_Resister = 2       
}ADC_Channel_Type;

void ADC_Init(void);
void ADC_CollectTemp(void);
void ADC_SerialOutMessage(void);
#endif

使用特权

评论回复
板凳
Ryanhsiung|  楼主 | 2011-10-14 10:33 | 只看该作者
注:若要调试本代码,最好请将WDT关闭,否则可以不能正常调试

使用特权

评论回复
地板
hotpower| | 2011-10-14 10:42 | 只看该作者
哈哈,零耗时并非不耗时,主要是避免等待。
像温度这样的“惰性气体”,它不可能突变。
故可以按自己的步调采集。
编程不要死板,非得要读取是访问硬件!
心中有个温度计,他要数据你就给他!

使用特权

评论回复
5
lixiaoxu2meng| | 2011-10-14 11:01 | 只看该作者
楼主的例程挺全啊  热敏电阻的我还没做 顶

使用特权

评论回复
6
Ryanhsiung|  楼主 | 2011-10-14 13:36 | 只看该作者
5# lixiaoxu2meng   这个是学习了你的例程后才写出来的

使用特权

评论回复
7
zxcscm| | 2012-2-16 22:34 | 只看该作者
AD_Value = ((((float)AD_Value)/4096)*-135)*((float)3300 /4095) + 85 ;
找来找去还是感觉这个温度校正的比较准

使用特权

评论回复
8
dong_abc| | 2012-2-17 00:05 | 只看该作者
感觉还是到手册上查表靠谱一些。

使用特权

评论回复
9
Ryanhsiung|  楼主 | 2012-2-18 08:22 | 只看该作者
感觉还是到手册上查表靠谱一些。
dong_abc 发表于 2012-2-17 00:05

热敏电阻就好用NTC,有公式可以计算!
    板上的电阻我是为了好算才视为线性的!

使用特权

评论回复
10
yongjun_meng| | 2012-4-14 07:49 | 只看该作者
谢谢分享!

使用特权

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

本版积分规则

认证:嵌入式技术专家
简介:道阻且长,行则将至!

64

主题

4654

帖子

14

粉丝