闲着蛋疼,Mega128本身自带AD,但是由于还处在学习阶段,于是用TWI与PCF8591进行通信,利用PCF8591读取ADC采样电压值,调节电位器,明明最大值是5V才对呀,可是扭开发板的电位器,电压从0V调节到2.5V,再变成0V,再往上调,最大才2.42V。调用的读函数用在24C02上可以正常读出数值。想了半天不知道哪里有问题。请高手帮忙看看!!!万分感谢,我是菜鸟初学者,还望高手不吝赐教
#include<iom128v.h>
#include<macros.h>
#pragma interrupt_handler timer1_ovf_isr:iv_TIM1_OVF
#define AddWr 0x90
#define AddRd 0x91
//MT模式:主机发送模式
#define START 0x08
#define RE_START 0x10
#define MT_SLA_ACK 0x18
#define MT_SLA_NOACK 0x20
#define MT_DATA_ACK 0x28
#define MT_DATA_NOACK 0x30
//MR模式:主机接收模式
#define START 0x08
#define RE_START 0x10
#define MR_SLA_ACK 0x40
#define MR_SLA_NOACK 0x48
#define MR_DATA_ACK 0x50
#define MR_DATA_NOACK 0x58
unsigned char TempData[];
unsigned char DuanMa[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
unsigned char WeiMa[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
unsigned char ReadAdcFlag;
#define START_I2C() {TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);}
#define STOP_I2C() {TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);}
#define WAIT() {while (!(TWCR & (1<<TWINT)));}
#define TWI() {TWCR = (1<<TWINT)|(1<<TWEN);}
#define SendByte(X) {TWDR = X; TWCR = (1<<TWINT) | (1<<TWEN);}
void Delayus(unsigned int US)
{
unsigned int i;
US=US*5/4;
for( i=0;i<US;i++);
}
void Delayms(unsigned int MS)
{
unsigned int i,j;
for( i=0;i<MS;i++)
for(j=0;j<1141;j++);
}
void Led_init(void)
{
DDRA = 0xff;
DDRF |= (1 << 3);
PORTA = 0xff;
PORTF |= (1 << 3);
PORTF &= ~(1 << 3);
}
void Seg_init(void)
{
DDRA = 0xff;
DDRC = 0xff;
DDRF |= ((1 << 1) | (1 << 2));
PORTC = 0xff;
PORTF |= (1 << 1);
PORTF &= ~(1 << 1);
PORTA = 0xff;
PORTF |= (1 << 2);
PORTF &= ~(1 << 2);
}
void Seg_Display(unsigned char firstbit,unsigned char weishu)
{
static unsigned char i;
PORTC = 0xff; //数码管消隐
PORTF |= BIT(1);
PORTF &= ~BIT(1);
PORTC = TempData[i];
PORTF |= BIT(1);
PORTF &= ~BIT(1);
PORTA = WeiMa[i+firstbit];
PORTF |= BIT(2);
PORTF &= ~BIT(2);
Delayms(1);
i++;
if(i == weishu)
i = 0;
}
unsigned char RevADC(unsigned char Channal)
{
unsigned char Val;
START_I2C(); //发出START 信号
WAIT(); //等待TWINT 置位, TWINT 置位表示START 信号已发出
if ((TWSR & 0xF8) != START) //检验TWI 状态寄存器,屏蔽预分频位,如果状态字不是START 转出错处理
return 0;
SendByte(AddWr); //将SLA_W 载入TWDR 寄存器, TWINT位清零,启动发送地址
WAIT(); //等待TWINT 置位, TWINT 置位表示总线命令SLA+W 已发出,及收到应答信号ACK/NACK
if ((TWSR & 0xF8) != MT_SLA_ACK) //检验TWI 状态寄存器,屏蔽预分频位,如果状态字不是MT_SLA_ACK 转出错处理
return 0;
SendByte(0x40 | Channal);
WAIT(); //等待TWINT 置位, TWINT 置位表示总线命令已发出,及收到应答信号ACK/NACK
if ((TWSR & 0xF8) != MT_DATA_ACK) //检验TWI 状态寄存器
return 0;
START_I2C(); //发出START 信号
WAIT(); //等待TWINT 置位, TWINT 置位表示START 信号已发出
if ((TWSR & 0xF8) != RE_START) //检验TWI 状态寄存器,屏蔽预分频位,如果状态字不是START 转出错处理
return 0;
SendByte(AddRd); //将SLA_W 载入TWDR 寄存器, TWINT位清零,启动发送地址
WAIT(); //等待TWINT 置位, TWINT 置位表示总线命令SLA+R 已发出,及收到应答信号ACK/NACK
if ((TWSR & 0xF8) != MR_SLA_ACK) //检验TWI 状态寄存器,屏蔽预分频位,如果状态字不是MR_SLA_ACK 转出错处理
return 0;
TWI(); //启动主I2C读方式
WAIT(); //等待TWINT 置位,及收到应答信号ACK/NACK
if ((TWSR & 0xF8) != MR_DATA_NOACK)
return 0;
Val = TWDR;
STOP_I2C();
return Val;
}
void Timer1_init(void)
{
TCCR1B = 0x00; //stop
TCNT1H = 0xFD; //setup
TCNT1L = 0x8F;
TCCR1B = 0x03; //start Timer
TIMSK = 0x04; //timer interrupt sources
SREG |= (1 << 7);
}
void main(void)
{
unsigned int num;
Led_init();
Seg_init();
Timer1_init();
while(1)
{
num = RevADC(0);
num = (num * 100 * 5)/255;
TempData[0] = DuanMa[num / 100] & 0x7f;
TempData[1] = DuanMa[(num % 100) / 10];
TempData[2] = DuanMa[num % 100 % 10];
}
}
void timer1_ovf_isr(void)
{
//TIMER1 has overflowed
TCNT1H = 0xFD; //reload counter high value
TCNT1L = 0x8F; //reload counter low value
Seg_Display(0,3);
} |