xwkm 发表于 2013-1-2 22:55:43

LGT内部的1.25V reg做参考的问题【已解决】

本帖最后由 xwkm 于 2013-1-2 23:08 编辑

编写了一个小程序:#include "RaysRTOS.h"

#include <stdio.h>
#define ADC_CHANNEL 0
#define VREF_VCC        1
#define VREF_1V5        2

#define ADC_GND                26
#define ADC_1V5                25

#define BAUDRATE 9600 //9600bps
/* ADC转换 */
volatile INT16U ADC_Convert(INT8U vref,INT8U channel)
{
      INT16U retval;

                ADMUX = ((vref << 6) | channel);       

                ADCSRA |= (1 << ADEN);                //使能 ADC

                //RAYS_TimeDelay(1);
                retval=0;

                ADCSRA |= (1 << ADSC);                //开始转换
       
                while(!(ADCSRA & (1 << ADIF)));
                ADCSRA |= (1 << ADIF);                //清除ADC中断标志
                for(retval=0;retval<1000;retval++);
                retval = ADC;
                return retval;
}
void ADC_Init()
{//启动ADC
        DIDR0=0xFF;//启动端口的模拟功能
        ADCSRA = 0x07;                        //32分频
}


void Serial_Init()
{//串口初始化,8MHz,9600bps
      UCSR0A=0x00;
      UBRR0H=0x00;
      UBRR0L=0x33;   //9600bps
      UCSR0B = 0x18; //0b00011000    允许:发送、接收
      UCSR0C = 0x0E; //0b00001110    数据帧格式:8,N,1
}

void _putchar(char c)
{
      while((UCSR0A & (1 << UDRE0)) == 0);
      UDR0 = c;

}

void putstr(unsigned char* buf)
{
      while (*buf)
      {
                _putchar(*buf);
                buf++;
      }
}
/*
+---------------------------------------------------------------------------------------+
|函数名称:        IdleTask                                                                                                                                        |
|---------------------------------------------------------------------------------------|
|函数原型:        void IdleTask(void)                                                                                                                        |
|                                                                                                                                                                                |
|函数功能:        电源电压检测&充电管理                                                                                                                                                   |
|                                                                                                                                                                                |
|有关说明:        空闲任务必须永远处于就绪状态                                                                                                        |
+---------------------------------------------------------------------------------------+
*/
void Task1(void)
{       
        volatile unsigned int voltage,t1,t2;
        char buff;
        asm("nop");
        ADC_Init();
        Serial_Init();
        sprintf(buff,"%s from Idle Process\n","Hello world!");
        putstr((void *)buff);
        while(1)
        {//每隔1s检测一次电源电压


                        /*putstr((void *)buff);*/
                       
                        t1=ADC_Convert(VREF_VCC,ADC_CHANNEL);
                        t2=0x00;
                        volatile t2=ADC_Convert(VREF_VCC,ADC_1V5);
                        //voltage=(1500/t2*t1)/10;
                        //voltage=(1250/t2*t1)/10;
                        sprintf(buff,"t1 %d,t2 %d,PA0 voltage:%d\n",t1,t2,voltage);
                        putstr((void *)buff);
                        RAYS_TimeDelay(100);
        }
}
用了RaysOS。论坛网友的一个小操作系统。我开了ICE跟踪。ADC值没有传错。
测试结果如下,PA0直接接VCC。但是程序算出来PA0的电压却是3.06V,不知道怎么解释!万用表测得3.32V

---------------不好意思我搞错了,内置的应该是1.25V的……

xwkm 发表于 2013-1-2 23:00:05

本帖最后由 xwkm 于 2013-1-2 23:43 编辑

刚才我发现貌似ADC和实际结果固定有一个20的差值……
后来发现其实最大的问题是我看错规格书了……
另外现在在linux下面也可以搞LGT了。给udev写这么一个rules:SUBSYSTEM!="usb_device", ACTION!="add", GOTO="avrisp_end"

# Atmel Corp. JTAG ICE mkII
ATTR{idVendor}=="03eb", SYSFS{idProduct}=="2103", MODE="660", GROUP="dialout"
# Atmel Corp. AVRISP mkII
ATTR{idVendor}=="03eb", SYSFS{idProduct}=="2104", MODE="660", GROUP="dialout"
# Atmel Corp. Dragon
ATTR{idVendor}=="03eb", SYSFS{idProduct}=="2107", MODE="660", GROUP="dialout"

LABEL="avrisp_end"加到/etc/udevd/rules.d/中
然后sudo restart udevd
就可以使用avrdude 了(前提是那个J2短路后要刷mkII的固件。别刷高,Studio4的即可
rgwan@rgwan-desktop:~$ avrdude -p m164p -c jtag2 -P usb

avrdude: jtagmkII_initialize(): warning: OCDEN fuse not programmed, single-byte EEPROM updates not possible
avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e1e1e
avrdude: Expected signature for ATMEGA164P is 1E 94 0A
         Double check chip, or use -F to override this check.

avrdude done.Thank you.

rgwan@rgwan-desktop:~$

dingshidong214 发表于 2013-1-2 23:26:59

自己给自己解决问题了,就是这样,把问题清清楚楚表述出来,你会发现问题已经解决一大半了,就怕不知怎么表达,但就是觉着怪,找不出根在哪里。

xwkm 发表于 2013-1-2 23:43:30

dingshidong214 发表于 2013-1-2 23:26 static/image/common/back.gif
自己给自己解决问题了,就是这样,把问题清清楚楚表述出来,你会发现问题已经解决一大半了,就怕不知怎么表 ...

其实很多时候我都这样了。后面一回头才发现哪里错误了……

HYLG 发表于 2013-1-3 00:12:29

LGT的AD值跳动有点大,进入AD噪声抑制模式有改观但还是有跳动。AVR就不存在这个问题。

xwkm 发表于 2013-1-3 01:51:30

HYLG 发表于 2013-1-3 00:12 static/image/common/back.gif
LGT的AD值跳动有点大,进入AD噪声抑制模式有改观但还是有跳动。AVR就不存在这个问题。 ...

不管了。反正只是电池电压检测而已。多测几次去掉最高最低就行了

xwkm 发表于 2013-1-3 01:58:44

本帖最后由 xwkm 于 2013-1-3 02:00 编辑

void Task1(void)
{       
        volatile unsigned int voltage,t1,t2;
        char buff;
        asm("nop");
        ADC_Init();
        Serial_Init();
        sprintf(buff,"%s from batt Process\n","Hello world!");
        putstr((void *)buff);
        while(1)
        {//每隔1s检测一次电源电压


                        /*putstr((void *)buff);*/
                       
                        t1=ADC_Convert(VREF_VCC,ADC_CHANNEL);
                        t2=ADC_Convert(VREF_VCC,ADC_1V5);
                        voltage=((13000/t2)*t1)/10;//LGT内部1.5V基准有固定的差值
                        //voltage=voltage * 10;
                        sprintf(buff,"t1 %d,t2 %d,PA0 voltage:%d mV \n",t1,t2,voltage);
                        putstr((void *)buff);
                        sprintf(buff,"Battery voltage:%d mV\n",voltage *2);//(voltage * 2)/1000);
                        putstr((void *)buff);
                        RAYS_TimeDelay(100);
        }
}
这个程序。我在上位机上看到的是:

确实有跳动。但是至少现在我还不太敏感。反正锂电池降到3650mV就直接PD的。
但是以后做充放电曲线的话这个东西可能还是需要外部基准。这个模拟板还在面包板上。可能跳动是因为干扰。明天整套系统完工应该就不会了

Yawgmoth 发表于 2013-1-25 15:54:30

HYLG 发表于 2013-1-3 00:12 static/image/common/back.gif
LGT的AD值跳动有点大,进入AD噪声抑制模式有改观但还是有跳动。AVR就不存在这个问题。 ...

话说怎么进入AD噪声抑制模式,我来回翻看文档,也没看见这个寄存器。。。

HYLG 发表于 2013-1-25 16:07:33

手册-系统时钟与功耗管理-睡眠模式。

Yawgmoth 发表于 2013-1-25 20:58:22

HYLG 发表于 2013-1-25 16:07 static/image/common/back.gif
手册-系统时钟与功耗管理-睡眠模式。

多谢。。。原来就在开头。。。

pupist 发表于 2013-3-20 10:29:46

为什么转换完成标志置位后要delay才读出呢?
页: [1]
查看完整版本: LGT内部的1.25V reg做参考的问题【已解决】