[Cortex-M0技术交流] RyanHsiung学习第二贴,0耗时 多路AD采集!

[复制链接]
 楼主| Ryanhsiung 发表于 2011-10-14 09:40 | 显示全部楼层 |阅读模式
本帖最后由 Ryanhsiung 于 2011-10-14 09:46 编辑

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


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

  6.     Button_Check();                                        //BUTTON检测
  7.         if(        count++ >= 10 )
  8.         {
  9.                 count = 0;
  10.                 ADC_CollectTemp();                        //AD检测
  11.         }
  12.         if(s_count++ >= 100  )
  13.         {
  14.                 s_count = 0;
  15.                 Flag_OneSecondForADC  = 1         ;                   //用于驱动AD信息输出        }
  16. }


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

  33. /*************************************************************************************
  34. ** Function name:       ADC_Variable_Init
  35. ** Descriptions:        ADC变量初始化
  36. ** input parameters:    none
  37. ** output parameters:   none
  38. ** Returned value:      none
  39. *************************************************************************************/
  40. void ADC_Variable_Init(void)
  41. {
  42.         uint8_t i;
  43.         //暂无 若无变量初始化,该函数可省略
  44.         ADC_Channel =  E_ADC_Channel_Chip_Temp;
  45.         for(i=0;i<ADC_CHANNEL_MAX_NUM;i++)
  46.         {
  47.                 ADC_CollectValue[i] =0;
  48.         }
  49. }
  50. /*************************************************************************************
  51. ** Function name:       ADC_Init
  52. ** Descriptions:        ADC初始化
  53. ** input parameters:    none
  54. ** output parameters:   none
  55. ** Returned value:      none
  56. *************************************************************************************/
  57. void ADC_Init(void)
  58. {
  59.         ADC_Configuration();
  60.         ADC_Variable_Init();                        
  61.         printf("ADC 初始完成!!\n");
  62. }
  63. /*************************************************************************************
  64. ** Function name:       ADC_CollectTemp
  65. ** Descriptions:        采集温度
  66. ** input parameters:    none
  67. ** output parameters:   none
  68. ** Returned value:      none
  69. ** Remark;                                AD采样很快,但是我每隔100MS才取一次
  70. *************************************************************************************/
  71. void ADC_CollectTemp(void)
  72. {        //若用单次采集则在采集完后必须重新打开采集
  73.         int32_t AD_Value;                                                                                        //用于存放AD值临时值                                                                  
  74.         if(DrvADC_IsConversionDone()==TRUE);                                                 // 判断ADC是否转换结束
  75.         { //不用等待,这里是0耗时的重点
  76.                 switch(ADC_Channel)
  77.                 {
  78.                         case E_ADC_Channel_Chip_Temp:         // 芯片温度
  79.                         {       
  80.                                 AD_Value = DrvADC_GetConversionData(7);                         //        取7通道,CHIP TEMP
  81.                                 AD_Value = AD_Value*3300/4095-730;                                         //         还需经过校正,现是套用他人的校正因子
  82.                                 AD_Value = AD_Value/-2;
  83.                                 ADC_CollectValue[ADC_Channel] = (uint8_t)AD_Value;
  84.                                 ADC_Channel = E_ADC_Channel_R_Temp;                                        //选择一下个通道
  85.                         }break;
  86.                         case E_ADC_Channel_R_Temp:            // 热敏电阻
  87.                         {        //这个热敏电阻是非线性的,所以换算比较难做,最好用查表
  88.                                 //我这里将10 - 40度近似看作为线性,中间的温度偏差可以有好几度。
  89.                                 //由于这个热敏电阻无太大意义,故方程我没有验证,请广大网友不要随意应用,若要用请验证!
  90.                                 AD_Value = DrvADC_GetConversionData(0);                                                                 //        取0通道,AD
  91.                                 AD_Value = ((((float)AD_Value)/4096)*-135)*((float)3300 /4095) + 85 ;         //         还需经过校正
  92.                                 ADC_CollectValue[ADC_Channel] = (uint8_t)AD_Value;                  
  93.                                 ADC_Channel = E_ADC_Channel_Resister;                                //选择一下个通道
  94.                         }break;
  95.                         case E_ADC_Channel_Resister:        // 可调电阻
  96.                         {                                                                  
  97.                                 AD_Value = DrvADC_GetConversionData(1);                         //        取1通道,AD
  98.                                 AD_Value = AD_Value*3300/4095;                                                //         还需经过校正
  99.                                 AD_Value = 100*((float)(3300 - AD_Value)/3300);
  100.                                 ADC_CollectValue[ADC_Channel] = (uint8_t)AD_Value;           
  101.                                 ADC_Channel = E_ADC_Channel_Chip_Temp;                                //选择一下个通道
  102.                         }break;
  103.                         default:break;
  104.                 }
  105.         }
  106. }
  107. /*************************************************************************************
  108. ** Function name:       ADC_SerialOutMessage
  109. ** Descriptions:        通过时间事件驱动,每隔1S通过串口发送一次数据给上位机
  110. ** input parameters:    none
  111. ** output parameters:   none
  112. ** Returned value:      none
  113. *************************************************************************************/
  114. void ADC_SerialOutMessage(void)
  115. {
  116.         if(Flag_OneSecondForADC)
  117.         {
  118.                 Flag_OneSecondForADC =0;
  119.                 printf("芯片温度:%d C   热阻温度: %d C  电阻阻值: %d(0.1kΩ) \n",\
  120.                                 ADC_CollectValue[0],ADC_CollectValue[1],ADC_CollectValue[2]);
  121.         }
  122. }
  123.                                  

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
 楼主| Ryanhsiung 发表于 2011-10-14 09:48 | 显示全部楼层
上面太长了,ADC.H内容,主要是定义了一个枚举类型
  1. #ifndef        __ADC_H
  2. #define        __ADC_H
  3. #include "Driver\DrvADC.h"
  4. #define ADC_CHANNEL_MAX_NUM                        3       
  5. typedef enum  type_ADC_Channel
  6. {
  7.         E_ADC_Channel_Chip_Temp = 0,
  8.         E_ADC_Channel_R_Temp = 1,
  9.         E_ADC_Channel_Resister = 2       
  10. }ADC_Channel_Type;

  11. void ADC_Init(void);
  12. void ADC_CollectTemp(void);
  13. void ADC_SerialOutMessage(void);
  14. #endif
 楼主| Ryanhsiung 发表于 2011-10-14 10:33 | 显示全部楼层
注:若要调试本代码,最好请将WDT关闭,否则可以不能正常调试
hotpower 发表于 2011-10-14 10:42 | 显示全部楼层
哈哈,零耗时并非不耗时,主要是避免等待。
像温度这样的“惰性气体”,它不可能突变。
故可以按自己的步调采集。
编程不要死板,非得要读取是访问硬件!
心中有个温度计,他要数据你就给他!
lixiaoxu2meng 发表于 2011-10-14 11:01 | 显示全部楼层
楼主的例程挺全啊  热敏电阻的我还没做 顶
 楼主| Ryanhsiung 发表于 2011-10-14 13:36 | 显示全部楼层
5# lixiaoxu2meng   这个是学习了你的例程后才写出来的
zxcscm 发表于 2012-2-16 22:34 | 显示全部楼层
AD_Value = ((((float)AD_Value)/4096)*-135)*((float)3300 /4095) + 85 ;
找来找去还是感觉这个温度校正的比较准
dong_abc 发表于 2012-2-17 00:05 | 显示全部楼层
感觉还是到手册上查表靠谱一些。
 楼主| Ryanhsiung 发表于 2012-2-18 08:22 | 显示全部楼层
感觉还是到手册上查表靠谱一些。
dong_abc 发表于 2012-2-17 00:05

热敏电阻就好用NTC,有公式可以计算!
    板上的电阻我是为了好算才视为线性的!
yongjun_meng 发表于 2012-4-14 07:49 | 显示全部楼层
谢谢分享!
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

64

主题

4653

帖子

14

粉丝
快速回复 在线客服 返回列表 返回顶部