公布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;
}
睡觉前顶下。。哎。。
求个人真难 {:cry:}{:cry:}
竟然木人回复。。。 顶顶吧,没用过这个编译器 垃圾一般的代码 错误那么多 不知道怎么编译通过生产HEX文件的 yklstudent 发表于 2012-10-20 08:04 static/image/common/back.gif
垃圾一般的代码 错误那么多 不知道怎么编译通过生产HEX文件的
怎么修改啊,大哥 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:45 编辑
对了 我这个把AD口改为AD0了
数码管位段口由PC口改为PB口
具体为:PC0-----PB0
PC1-----PB1
PC2-----PB2
PC3-----PB3 还有那些变量加上volatile不然好像要被GCC优化掉 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 static/image/common/back.gif
中断好像可以工作了,但是数据根本对不上啊
下面是截图
这是我运行的效果 显示没问题。。你自己再看看吧 mark 收藏 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;
}
}
厚着脸皮,说一句,能否上传下你的工程??呵呵
谢谢 换了未选线的顺序还是一样的,奇怪了,,
怎么你的正常,我的是乱七八糟 的数据? yklstudent 发表于 2012-10-20 13:38 static/image/common/back.gif
对了 我这个把AD口改为AD0了
数码管位段口由PC口改为PB口
具体为:PC0-----PB0
我也这样修改的,其他什么都没动过?????
什么原因
chary_5 发表于 2012-10-21 11:22 static/image/common/back.gif
我也这样修改的,其他什么都没动过?????
什么原因
这个就是全部,HEX文件是default内的 外面的HEX是你老得 yklstudent 发表于 2012-10-21 14:33 static/image/common/back.gif
这个就是全部,HEX文件是default内的 外面的HEX是你老得
大哥,你hex显示结果是和你说的一致
但没有给出源代码啊,你在前面给出的源代码根本显示不了哦
救人救到底吧,谢谢 本帖最后由 yklstudent 于 2012-10-21 18:03 编辑
chary_5 发表于 2012-10-21 16:18 static/image/common/back.gif
大哥,你hex显示结果是和你说的一致
但没有给出源代码啊,你在前面给出的源代码根本显示不了哦
救人救到 ...
那个C文件就是 不是有个C文件嘛 程序就是那个 可以编译的 生成的HEX文件在default文件夹下就对了那个才是 呵呵,default下没有代码文件哦
还有哦,AD下的hex大小不到2KB,
default下Hex大小是12KB
chary_5 发表于 2012-10-21 18:22 static/image/common/back.gif
呵呵,default下没有代码文件哦
哎 表达能力问题差了
你上面的图片里的M8_AD.c文件不就程序嘛
那个就是你还要上面 AD文件下得.HEX是你以前的
default文件下得.HEX是改后的那个就是M8_AD.c文件编译生成的 多谢大侠这么热心的帮助
奇怪了,用default下的Makefile编译出来的就正常,用AD下的就不显示第二位了,
而且两者编译出来大小相差很大。。。
研究下Makefile导致的原因
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;
} ada=(v+3)*30/128;//这句话什么意思???
页:
[1]