chary_5 发表于 2012-10-18 22:17:34

公布M8电压表全部代码和仿真,顺便请教个问题

初学AVR,参考网上的源代码做了电压表,使用AD中断,但中断不能正常工作
Result is not written to the ADC register because it has been locked.
一直这样提示
先谢谢各位看官了,小弟都折腾了好几天了,没有进展,希望各位多多指点

源代码工程和仿真工程

源代码#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <avr/wdt.h>
#include <avr/delay.h>
#define uchar unsigned char
#define uint unsigned int

uchar Table={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//共阴
//uchar Table={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,};//共阳
uchar Data={0,0,0,0};

static uint ADValue = {0};//AD采样值
static uint g_nAdValue=0;//平均电压
static ADTimes=0;   //AD采样次数,第几次采样
static        tmp16; //AD采样和

void Display(uchar *p) //间隔5ms显示
{

        uchar i,sel=0x01;
for(i=0;i<4;i++)
{
PORTC=sel;
if(i==2)
    PORTD=0x7f-Table]; //0111 1111
else PORTD=0xff-Table];
   _delay_ms(10);
   sel=sel<<1;
}
}

/*
void Display(uchar *p) //间隔5ms显示
{
uchar sel=0x01;
for(uchar i=0;i<4;i++)
{
PORTC=~sel;
if(i==2)
    PORTD= Table] + 0x80; //0111 1111 1000 0000
else
        PORTD = Table];
   _delay_ms(10);
   sel=sel<<1;
}
}
*/

void Process(uint i,uchar *p)
{
        for(uchar j = 0; j < 4; j++)
        p = 0;
       
p=i/1000;
i=i%1000;
p=i/100;
i=i%100;
p=i/10;
i=i%10;
p=i;
}

void port_init()
{
        DDRB=0xf0;                  //set port b as input port 1111 0000 the first 4 bits as output, the latter 4 bits as input
PORTB=0xff;
DDRC=0x0f;                  //设置C口为推挽1输出;
PORTC=0x00;
DDRD=0xff;                  //设置C口为推挽1输出;
PORTD=0xff;
PORTB=0x00;                  
PORTD=0x00;
}

//********************************************************
//函数名:Timer0_Init
//输入:无
//输出:无
//描述:ATmega 8 Timer0 初始化,中断周期10ms
//********************************************************
void Timer0_Init(void)
{
        TCCR0=0x04;//256分频,8M/1024,
        TCNT0=0X00;//计数器清零
        TIMSK|=0x01;//使能TOIE0中断
        TIFR|=0X01; //清楚中断标识位
}
//********************************************************
//函数名:SIGNAL(SIG_ADC)
//输入:无
//输出:无
//描述:AD测量中断服务程序
//********************************************************

SIGNAL(SIG_ADC)
{

ADCSRA|=(1<<ADSC);
ADValue=(ADCH<<8);
        ADValue|=ADCL;
        //ADValue|=(ADCH<<8);
        ADTimes++;
        if( ADTimes>=16)
        {       
            ADTimes = 0;
                tmp16=0;
                for(char n=0;n<16;n++ )
                {
                        tmp16+=ADValue;
                }
                g_nAdValue = tmp16/16;
       
        }
}

void adc_init()
{

ADMUX = 0B00000100;                // INTERNAL Vref 2.56V select first ADC4;0000 0100

//        ADCSRA = 0B11000111;//0xc7
        ADCSRA=_BV(ADEN)|_BV(ADIE)|_BV(ADFR)|_BV(ADPS1)|_BV(ADPS0);
        ADCSRA|=_BV(ADSC);//自由模式开始转换
       
}


int main(void)
{
        port_init();
        adc_init();
_delay_ms(500);                //延时待系统稳定;
        uint ada ,i,v;
       
        wdt_enable(WDTO_1S);
        sei();
while(1)
{
          cli();
                v= g_nAdValue;
                ada=(v+3)*30/128;

        Process(ada,Data);
           Display(Data);

        sei();
                wdt_reset();//喂狗
}

return 0;
}

chary_5 发表于 2012-10-18 22:58:37

睡觉前顶下。。哎。。
求个人真难

chary_5 发表于 2012-10-19 20:46:45

{:cry:}{:cry:}
竟然木人回复。。。

guxingganyue 发表于 2012-10-19 22:28:43

顶顶吧,没用过这个编译器

yklstudent 发表于 2012-10-20 08:04:48

垃圾一般的代码 错误那么多 不知道怎么编译通过生产HEX文件的

chary_5 发表于 2012-10-20 10:06:41

yklstudent 发表于 2012-10-20 08:04 static/image/common/back.gif
垃圾一般的代码 错误那么多 不知道怎么编译通过生产HEX文件的

怎么修改啊,大哥

yklstudent 发表于 2012-10-20 13:37:15

chary_5 发表于 2012-10-20 10:06 static/image/common/back.gif
怎么修改啊,大哥

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
#ifndef F_CPU
#define F_CPU        8000000
#endif
#include <util/delay.h>
#define uchar unsigned char
#define uint unsigned int

uchar Table={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//共阴
//uchar Table={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,};//共阳
uchar Data={0,1,2,3};

volatile uint ADValue = {0};//AD采样值
volatile uint g_nAdValue=0;//平均电压
volatile uint ADTimes=0;   //AD采样次数,第几次采样
volatile uint tmp16; //AD采样和

void Display(uchar *p) //间隔5ms显示
{
        uchar i,sel=0x01;
        for(i=0;i<4;i++)
        {
                PORTB=sel;
                if(i==2)
                    PORTD=0x7f-Table]; //0111 1111
                else
                        PORTD=0xff-Table];
                   _delay_us(10);
                   sel=sel<<1;
        }
}

/*
void Display(uchar *p) //间隔5ms显示
{
uchar sel=0x01;
for(uchar i=0;i<4;i++)
{
PORTC=~sel;
if(i==2)
    PORTD= Table] + 0x80; //0111 1111 1000 0000
else
        PORTD = Table];
   _delay_ms(10);
   sel=sel<<1;
}
}
*/

void Process(uint i,uchar *p)
{
        p=i/1000;
        i=i%1000;
        p=i/100;
        i=i%100;
        p=i/10;
        i=i%10;
        p=i;
}

void port_init()
{
        DDRB=0xff;                  //set port b as input port 1111 0000 the first 4 bits as output, the latter 4 bits as input
        PORTB=0xff;
        DDRC=0x00;                  //设置C口为推挽1输出;
        PORTC=0x00;
        DDRD=0xff;                  //设置C口为推挽1输出;
        PORTD=0xff;
        PORTB=0x00;                  
        PORTD=0x00;
}

//********************************************************
//函数名:Timer0_Init
//输入:无
//输出:无
//描述:ATmega 8 Timer0 初始化,中断周期10ms
//********************************************************
void Timer0_Init(void)
{
        TCCR0=0x04;//256分频,8M/1024,
        TCNT0=0X00;//计数器清零
        TIMSK|=0x01;//使能TOIE0中断
        TIFR|=0X01; //清楚中断标识位
}

void Start_ADC(void)
{
        ADCSRA |= _BV(ADIE);
        ADMUX = 0x00;
        _delay_us(2);
        ADCSRA |= _BV(ADSC);
}


void Stop_ADC(void)
{
        ADCSRA &= ~_BV(ADIE);
}

//********************************************************
//函数名:SIGNAL(SIG_ADC)
//输入:无
//输出:无
//描述:AD测量中断服务程序
//********************************************************
SIGNAL(SIG_ADC)
{
        uchar n;
        ADValue = (ADCL+ADCH*256);
        //g_nAdValue = ADValue;
        if(ADTimes>=16)
        {       
                tmp16=0;
                for(n=0;n<16;n++ )
                {
                        tmp16+=ADValue;
                }
                g_nAdValue = (tmp16>>4);
                   ADTimes = 0;
        }
          
}

void adc_init()
{
        ADMUX = 0B00000000;                // INTERNAL Vref 2.56V select first ADC4;0000 0100
        ADCSRA=_BV(ADEN)|_BV(ADIE)|_BV(ADPS2)|_BV(ADPS1)|_BV(ADPS0);       
}

/*
void adc_init()
{
        ADMUX = 0B00000000;                // INTERNAL Vref 2.56V select first ADC4;0000 0100
        ADCSRA = 0xC5;
}

uint ADC_READ(void)
{
        ADCSRA |= _BV(ADSC);
        while((ADCSRA&_BV(ADIF))==0X10);
        return (ADCL+ADCH*256);
}
*/

int main(void)
{
        uint ada,v;
        _delay_ms(500);                //延时待系统稳定;
        port_init();
        adc_init();
       
        //wdt_enable(WDTO_1S);
        sei();
        //Start_ADC();
        while(1)
        {
                  //cli();
                //g_nAdValue = ADC_READ();
                Start_ADC();
                v= g_nAdValue;
                ada=(v+3)*30/128;

                Process(ada,Data);
                   Display(Data);
                Stop_ADC();
                //wdt_reset();//喂狗
        }
        return 0;
}

哎 这里资料那么多 怎么就不知道有效利用呢

yklstudent 发表于 2012-10-20 13:38:34

本帖最后由 yklstudent 于 2012-10-20 13:45 编辑

对了 我这个把AD口改为AD0了
数码管位段口由PC口改为PB口
具体为:PC0-----PB0
             PC1-----PB1
             PC2-----PB2
             PC3-----PB3

yklstudent 发表于 2012-10-20 13:39:31

还有那些变量加上volatile不然好像要被GCC优化掉

chary_5 发表于 2012-10-20 22:22:02

yklstudent 发表于 2012-10-20 13:38 static/image/common/back.gif
对了 我这个把AD口改为AD0了
数码管位段口由PC口改为PB口
具体为:PC0-----PB0


非常感谢LS的指点
我现在编译试试

chary_5 发表于 2012-10-20 22:52:26

中断好像可以工作了,但是数据根本对不上啊
下面是截图

yklstudent 发表于 2012-10-20 23:57:55

chary_5 发表于 2012-10-20 22:52 static/image/common/back.gif
中断好像可以工作了,但是数据根本对不上啊
下面是截图

这是我运行的效果 显示没问题。。你自己再看看吧

stmmcu 发表于 2012-10-21 05:03:44

mark 收藏

chary_5 发表于 2012-10-21 10:36:51

yklstudent 发表于 2012-10-20 23:57 static/image/common/back.gif
这是我运行的效果 显示没问题。。你自己再看看吧

我修改了这个地方,加了红色的地方,否则编译报错

void Display(uchar *p) //间隔5ms显示
{
      uchar i,sel=0x01;
      for(i=0;i<4;i++)
      {
                  PORTB=sel;
                  if(i==2)
                  PORTD=0x7f-Table]; //0111 1111
                  else
                        PORTD=0xff-Table];
                   _delay_us(10);
                   sel=sel<<1;
      }
}

厚着脸皮,说一句,能否上传下你的工程??呵呵
谢谢

chary_5 发表于 2012-10-21 10:48:41

换了未选线的顺序还是一样的,奇怪了,,
怎么你的正常,我的是乱七八糟 的数据?

chary_5 发表于 2012-10-21 11:22:17

yklstudent 发表于 2012-10-20 13:38 static/image/common/back.gif
对了 我这个把AD口改为AD0了
数码管位段口由PC口改为PB口
具体为:PC0-----PB0


我也这样修改的,其他什么都没动过?????
什么原因

yklstudent 发表于 2012-10-21 14:33:59

chary_5 发表于 2012-10-21 11:22 static/image/common/back.gif
我也这样修改的,其他什么都没动过?????
什么原因

这个就是全部,HEX文件是default内的 外面的HEX是你老得

chary_5 发表于 2012-10-21 16:18:16

yklstudent 发表于 2012-10-21 14:33 static/image/common/back.gif
这个就是全部,HEX文件是default内的 外面的HEX是你老得

大哥,你hex显示结果是和你说的一致
但没有给出源代码啊,你在前面给出的源代码根本显示不了哦
救人救到底吧,谢谢

yklstudent 发表于 2012-10-21 17:58:26

本帖最后由 yklstudent 于 2012-10-21 18:03 编辑

chary_5 发表于 2012-10-21 16:18 static/image/common/back.gif
大哥,你hex显示结果是和你说的一致
但没有给出源代码啊,你在前面给出的源代码根本显示不了哦
救人救到 ...

那个C文件就是

yklstudent 发表于 2012-10-21 18:02:06

不是有个C文件嘛 程序就是那个 可以编译的 生成的HEX文件在default文件夹下就对了那个才是

chary_5 发表于 2012-10-21 18:22:57

呵呵,default下没有代码文件哦



还有哦,AD下的hex大小不到2KB,
default下Hex大小是12KB



yklstudent 发表于 2012-10-21 20:27:38

chary_5 发表于 2012-10-21 18:22 static/image/common/back.gif
呵呵,default下没有代码文件哦




哎 表达能力问题差了
你上面的图片里的M8_AD.c文件不就程序嘛
那个就是你还要上面

yklstudent 发表于 2012-10-21 20:29:28

AD文件下得.HEX是你以前的
default文件下得.HEX是改后的那个就是M8_AD.c文件编译生成的

chary_5 发表于 2012-10-21 21:18:17

多谢大侠这么热心的帮助
奇怪了,用default下的Makefile编译出来的就正常,用AD下的就不显示第二位了,
而且两者编译出来大小相差很大。。。
研究下Makefile导致的原因

chary_5 发表于 2012-10-26 23:04:43

int main(void)
{
      uint ada,v;
      _delay_ms(500);                //延时待系统稳定;
      port_init();
      adc_init();
      
      //wdt_enable(WDTO_1S);
      sei();
      //Start_ADC();
      while(1)
      {
                  //cli();
                //g_nAdValue = ADC_READ();
                Start_ADC();
                v= g_nAdValue;
                ada=(v+3)*30/128;//这句话什么意思???

                  Process(ada,Data);
                   Display(Data);
                Stop_ADC();
                //wdt_reset();//喂狗
      }
      return 0;
}

chary_5 发表于 2012-10-26 23:04:59

ada=(v+3)*30/128;//这句话什么意思???
页: [1]
查看完整版本: 公布M8电压表全部代码和仿真,顺便请教个问题