zoukankan      html  css  js  c++  java
  • ZigBee心电传输(二)

    不管怎样,还是在高手的帮助下完成了前面的硬件部分,现在进行ZigBee的心电AD采集和转换。需要把ZigBee重新拾起来。

    首先明确下目标和思路吧,目标是将模拟心电信号通过AD转换,变为数字信号,再用ZigBee传输出来。思路是利用Zstack协议栈,来写程序,通过ADC触发DMA,触发事件,将数据传输到串口或者直接从无线发送出去。

    首先是ADC的配置,要配置就必须了解ADC的几个寄存器了。

    包括:ADCCFG,ADCCON1,ADCCON2,ADCCON3,ADCH和ADCL

    cc2430的ADC可以使用多达八个ADC输入引脚,要配置一个端口0引脚为一个ADC输入,ADCCFG寄存器相应的位置1,这个寄存器选择端口0引脚为非ADC输入。在使用ADC时,通过在ADCCFG寄存器的初始化代码中设置所需的位,ADCCFG寄存器的设置将覆盖P0SEL的设置。

    接下来就是3个控制寄存器,ADCCON1是EOC-ST-STSEL[1:0]-RCTRL[1:0]-保留(11),其中EOC当被ADCH和ADCL被读取后才清零。ST表示开始转换,设置成1后,转换完成了会清零。STSEL表示启动转换的选择,00为外部触发,01为全速转换,10为定时器1的通道0的比较事件,11表示ST为1;低4位不涉及,可以全部置1.

    ADCCON2,SREF[1:0]-SDIV[1:0]-SCH[3:0],SREF用于设置参考电压,00为内部参考电压,01为AIN7上的外部参考电压,10为AVDD_SOC引脚的电压,11为AIN6和AIN7的差分输入电压。SDIV表示抽取率,决定了采样时间和分辨率。SCH表示序列通道选择。

    ADCCON3类似ADCCON2,用于额外采样。

    其次,怎样写程序是AD工作,并且将数据读出来,用数字量表示。

    这一步是关键,心电的ADC采样到底怎么来设置才能读出数据呢。得一步一步试试。

    参照晚上的一些心电程序:http://blog.csdn.net/ohexiwei/article/details/8013570

    差不多能知道配置过程,经过一些尝试我的初步配置过程如下:

    static uint8 adcRef;
    static int16 reading = 0;

    void HalAdcInit (void)
    {
    #if (HAL_ADC == TRUE)
    adcRef = HAL_ADC_REF_AVDD;
    #endif
    }

    uint16 HalAdcseriesRead (uint8 channel, uint8 resolution)
    {

    uint8 i, resbits;
    uint8 adcChannel = 1;
    /*
    * If Analog input channel is AIN0..AIN7, make sure corresponing P0 I/O pin is enabled. The code
    * does NOT disable the pin at the end of this function. I think it is better to leave the pin
    * enabled because the results will be more accurate. Because of the inherent capacitance on the
    * pin, it takes time for the voltage on the pin to charge up to its steady-state level. If
    * HalAdcRead() has to turn on the pin for every conversion, the results may show a lower voltage
    * than actuality because the pin did not have time to fully charge.
    */
    if (channel < 8)
    {
    for (i=0; i < channel; i++)
    {
    adcChannel <<= 1;
    }
    }
    /* Enable channel */
    ADCCFG |= adcChannel;
    /* Convert resolution to decimation rate */
    switch (resolution)
    {
    case HAL_ADC_RESOLUTION_8:
    resbits = HAL_ADC_DEC_064;
    break;
    case HAL_ADC_RESOLUTION_10:
    resbits = HAL_ADC_DEC_128;
    break;
    case HAL_ADC_RESOLUTION_12:
    resbits = HAL_ADC_DEC_256;
    break;
    case HAL_ADC_RESOLUTION_14:
    default:
    resbits = HAL_ADC_DEC_512;
    break;
    }
    /* writing to this register starts the extra conversion */
    ADCCON3 = channel | resbits | adcRef ;

    ADCCON1 |= HAL_ADC_STSEL_ST;

    ADCCON1 |= HAL_ADC_START;
    /* Wait for the conversion to be done */
    while (!(ADCCON1 & HAL_ADC_EOC));

    /* Disable channel after done conversion */
    ADCCFG &= (adcChannel ^ 0xFF);

    /* Read the result */
    reading = (uint16)ADCL;
    reading |=(uint16)(ADCH << 8);

    /* Treat small negative as 0 */
    /*if (reading < 0)
    reading = 0;*/


    switch (resolution)
    {
    case HAL_ADC_RESOLUTION_8:
    reading >>= 8;
    break;
    case HAL_ADC_RESOLUTION_10:
    reading >>= 6;
    break;
    case HAL_ADC_RESOLUTION_12:
    reading >>= 4;
    break;
    case HAL_ADC_RESOLUTION_14:
    default:
    reading >>= 2;
    break;
    }
    return ((uint16)reading);
    }

    讲一下我的配置过程吧:首先是参考电压,选择一般网上程序都用的HAL_ADC_REF_AVDD,什么意思,就是外部的一个参考电压,这个电压加在引脚:AVDD_SOC上,我看了一下我的板子,刚好这个脚是接在3.3的电源电压上。接下来是分辨率/抽取率选择14位的,对于新手总是觉得越大越好,通道我选择了0通道。然后是ADCCON1进行控制了,就两个语句ADCCON1 |= HAL_ADC_STSEL_ST;ADCCON1 |= HAL_ADC_START;这两个语句就是开启转换的一个命令,接下来是

    /* Wait for the conversion to be done */
    while (!(ADCCON1 & HAL_ADC_EOC));

    /* Disable channel after done conversion */
    ADCCFG &= (adcChannel ^ 0xFF);

    /* Read the result */
    reading = (uint16) (ADCL);
    reading |= (uint16) (ADCH << 8);

    等待转换结束,读取数据。好了加电调试,有数据出来了,不过问题也来了,出来的数据不对,数据都是10000以上的,

    对照数据手册,可以知道,电压值对应从ADCH和ADCL读出来的数据。如下:

    这就奇怪了,最大才8191,刚开始以为我以为是reading的数据类型问题,我将reading统统改成uint16,还是一样,都会超过8191,也就是意味着这个电压是个负值,可是怎么可能呢,我加的一直是正电压(这里注意了一下,我用信号发生器产生信号,一定要加一个正偏置的电压,否则输出会有负值,这个新手不太注意,负值大了会把管脚烧坏),所以还是各种不解。继续分析吧从每个配置开始,首先我不确定的是VREF,这里的VREF我纠结了好久,数据手册里面也没有再提到。后来才知道,这个VREF就是对应ADCCON2和ADCCON3寄存器中所说的参考电压。我对寄存器改了好几次,改成内部参考电压,AIN7引脚输如的外部电压,差分方式没试,都不对,都还是负值,大于8191。又查了数据类型的定义,cc2530的定义如下:

    /* ------------------------------------------------------------------------------------------------
    * Types
    * ------------------------------------------------------------------------------------------------
    */
    typedef signed char int8;
    typedef unsigned char uint8;

    typedef signed short int16;
    typedef unsigned short uint16;

    typedef signed long int32;
    typedef unsigned long uint32;

    typedef unsigned char bool;

    typedef uint8 halDataAlign_t;

    很基本的,都对。接下来再看看分辨率,这时我想起了,一个帖子cc2430和cc2530的不同:http://blog.csdn.net/xukai871105/article/details/7318886

    里面讲到了cc2530和2430,ADC分辨率虽然有14位的选项,但是硬件上其实没有达到这个精度和水平,所以软件配置都是12最高了,那么就对了,我一直配置的是14位,但是数据读出来是12位的,怪不得老是大很多,2位刚好是4倍,我给一个1.5v的电压应该是4000多的值,却返回16000多的,这不是刚好4倍,终于找到根源了,两天了。。。。

    立马我把配置改成12位的,果然,数据稳定了,而且都在0-8191之间了。加上方波,出现了高低的正常波形数据。。。。!!!感动的啊,我终于自己也解决了个问题了。接下来我想验证一下这个14位和12位的关系,我将配置改成14位,然后将读出来的数据右移2位,读数据,果然啊,和12位一样了,稳定!

    总算是把问题解决了。

    next,加上心电的波形再试试。后面再加上自己的帧格式,就能传输心电波形了哈!

  • 相关阅读:
    notepad++ 安装
    Git 安装
    C 字符串常量 数据类型
    vue路由传参query和params的区别
    mysql 在 centos 上安装,做成服务,且开机启动 步骤
    全网最详细Apache Kylin1.5安装(单节点)和测试案例 ---> 现在看来 kylin 需要 安装到Hadoop Master 节点上
    Kylin build cube step 2 报错(Kylin 安装在slave 节点上)
    Kylin build cube step 2 报错
    Kylin 环境 搭建 成功
    Kylin 环境 搭建 报错
  • 原文地址:https://www.cnblogs.com/preorder69/p/3358539.html
Copyright © 2011-2022 走看看