乡亲们,看看这个PCF8591驱动,怎么弄
#include <avr/io.h>#include <util/delay.h>
#include <util/twi.h>
#include <avr/interrupt.h>
typedef unsigned char uint8;
typedef unsigned intuint16;
#define SETBIT(val,bitn) (val |= 1<<bitn)
#define CLRBIT(val,bitn) (val &= ~(1<<bitn))
#define GETBIT(val,bitn) ((val >> bitn)&0x01)
#define REVERBIT(val,bitn) (val ^= ~(1<<bitn) )
#define ADDR_PCF 0x00//定义PCF8591的硬件地址
#define AddWr 0x90 //写数据地址
#define AddRd 0x91 //读数据地址
volatile uint8 ADFlag=0;
#define PCF_SDA0() CLRBIT(PORTC,PC0)
#define PCF_SDA1() SETBIT(PORTC,PC0)
#define PCF_SCK0() CLRBIT(PORTC,PC1)
#define PCF_SCK1() SETBIT(PORTC,PC1)
/* 启动IIC总线
------------------------------------------------*/
void Start(void)
{
//Sda=1;
DDRC |= 0x03; //低俩位始终为输出。
PCF_SDA1(); _delay_us(10);
PCF_SCK1();_delay_us(10);
PCF_SDA0(); _delay_us(10);
PCF_SCK0(); //_delay_us(5);
}
/*------------------------------------------------
停止IIC总线
------------------------------------------------*/
void Stop(void)
{
/*Sda=0;
_nop_();
Scl=1;
_nop_();
Sda=1;
_nop_();
Scl=0;
*/
DDRC |= 0x03; //低俩位始终为输出。
PCF_SDA0(); _delay_us(10);
PCF_SCK1(); _delay_us(10);
PCF_SDA1(); _delay_us(10);
// PCF_SCK0();
}
/*------------------------------------------------
应答IIC总线
------------------------------------------------*/
void Ack(void)
{
/*Sda=0;
_nop_();
Scl=1;
_nop_();
Scl=0;
_nop_();
*/
DDRC |= 0x03; //低俩位始终为输出。
PCF_SDA0(); _delay_us(10);
PCF_SCK1(); _delay_us(10);
PCF_SCK0(); _delay_us(10);
}
/*------------------------------------------------
非应答IIC总线
------------------------------------------------*/
void NoAck(void)
{
/*Sda=1;
_nop_();
Scl=1;
_nop_();
Scl=0;
_nop_();
*/
DDRC |= 0x03; //低俩位始终为输出。
PCF_SDA1(); _delay_us(10);
PCF_SCK1(); _delay_us(10);
PCF_SCK0(); _delay_us(10);
}
/*------------------------------------------------
发送一个字节
------------------------------------------------*/
void Send(unsigned char Data)
{
DDRC |= 0x03; //低俩位始终为输出。
unsigned char BitCounter=8;
unsigned char temp;
do
{
temp=Data;
PCF_SCK0(); _delay_us(10);
if((temp&0x80)==0x80)
PCF_SDA1();
else
PCF_SDA0();
PCF_SCK1();
temp=Data<<1;
Data=temp;
BitCounter--;
}
while(BitCounter);
PCF_SCK0();
}
/*------------------------------------------------
读入一个字节并返回
------------------------------------------------*/
unsigned char Read(void)
{
DDRC |= 0x03; //低俩位始终为输出。
unsigned char temp=0;
unsigned char temp1=0;
unsigned char BitCounter=8;
PCF_SDA1();
do
{
PCF_SCK0(); _delay_us(10);
PCF_SCK1(); _delay_us(10);
//CLRBIT(DDRC,PC0);
DDRC =0x00; PORTC |= 0x01;
// if( GETBIT(PINC,PC0)==1)
if ( (PINC & 0x01)==1) temp=temp|0x01;
else
temp=temp&0xfe;
DDRC |= 0x03;
if(BitCounter-1)
{
temp1=temp<<1;
temp=temp1;
}
BitCounter--;
}
while(BitCounter);
return temp;
}
/*------------------------------------------------
写入DA数模转换值
------------------------------------------------*/
void DAC(unsigned char Data)
{
Start();
Send(AddWr); //写入芯片地址
Ack();
Send(0x40);//写入控制位,使能DAC输出
Ack();
Send(Data);//写数据
Ack();
Stop();
}
/*------------------------------------------------
读取AD模数转换的值,有返回值
------------------------------------------------*/
unsigned char ReadADC(unsigned char Chl)
{
unsigned char Data=9;
Start(); //写入芯片地址
Send(0x90);
Ack();
Send(0x40|Chl);//写入选择的通道,本程序只用单端输入,差分部分需要自行添加
//Chl的值分别为0、1、2、3,分别代表1-4通道
Ack();
Start();
Send(0x91); //读入地址
Ack();
Data=Read(); //读数据
PCF_SCK0();
NoAck();
Stop();
return Data; //返回值
}
void USART_Init()
{
UCSRA=0x00; //单倍速模式
UCSRB = 0x00;
UCSRB=0x18; //接收中断和发送中断使能
UBRRH=(F_CPU/9600/16-1)/256;
UBRRL=(F_CPU/9600/16-1)%256;
UCSRC= (1<<URSEL) | (1<<UCSZ0) | (1<<UCSZ1);//加不加都行,因为设定了UCSR0C=0x86;
}
void putch(unsigned char data)
{
while (!( UCSRA & (1<<UDRE))); //表明发送器一准备就绪
UDR = data;
}
/*------------------------------------------------
主程序
------------------------------------------------*/
int main()
{
unsigned char num; //DA数模输出变量
uint8 ADtemp=0; //定义中间变量
uint8 n=0;
USART_Init();
DDRC = 0xff;
while(1)
{
DAC(num); //DA输出,可以用LED模拟电压变化
num++; //累加,到256后溢出变为0,往复循环。显示在LED上亮度逐渐变化
_delay_ms(20); //延时用于清晰看出变化
putch(0x30 + (uint8)(ReadADC(3)) );
// putch(0x30 + (uint8)(ReadADC(0)*196/10000));
// putch(0x30 + (uint8)(ReadADC(1)*196/10000));
// putch(0x30 + (uint8)(ReadADC(2)*196/10000));
// putch(0x30 + (uint8)(ReadADC(3)*196/10000));
putch(' ');
n++;
if(n==10){putch('\n');n=0;}
_delay_ms(80);
}
return 0;
}
为啥我的读取错误?但DA没问题。读取不是5就是/,要不就是? 没人吗?求解啊
页:
[1]