本帖最后由 芯圣电子官方QQ 于 2023-7-19 16:41 编辑
今天搞了一下PCF8591,本来PCF8591既有DAC功能,又有ADC功能。
可我只搞出了DAC,ADC一直不对。
SCL接P01,SDA接P00。
代码:
#define ALLOCATE_EXTERN
#include "HC89S105AC8.h"
#include "i2c.h"
#define uint8_t unsigned char
#define uint16_t unsigned int
#define PCF8591 0x90 //PCF8591 地址
#define SCL P0_1 //I2C时钟控制位
#define SDA P0_0
unsigned char AD_CHANNEL;
unsigned char DAC_VALUE=0;
unsigned char ADCVALUE=0;
unsigned char txBuf[]={"ADC VALUE=: \r\n"};
// 函数申明
void delay(uchar i);
/***************************************************************************************
* @说明 IIC发送一个字节的数据
* @参数 fuc_Add:存储的地址
* fuc_Dat:存储的数据
* @返回值 无
* @注 无
***************************************************************************************/
void DACconversion(unsigned char fuc_Add, unsigned char fuc_Dat)
{
IICCON &= ~0x08; //清除中断标志位
IICCON |= 0x20; //起始位发送起始信号
while ((!(IICCON & 0x08)) && (IICSTA != 0x08));
IICCON &= ~0x20; //起始位停止起始信号
IICCON &= ~0x08; //清除中断标志位
IICDAT = PCF8591; //写入器件地址
while (IICSTA != 0x18);
IICCON &= ~0x08; //清除中断标志位
IICDAT = fuc_Add; //写入地址
while (IICSTA != 0x28);
IICCON &= ~0x08; //清除中断标志位
IICDAT = fuc_Dat; //写入数据
while (IICSTA != 0x28);
IICCON &= ~0x08; //清除中断标志位
IICCON |= 0x10; //停止位发送停止信号
}
unsigned char ADC(unsigned char fuc_Add)
{
unsigned char fuc_Dat;
IICCON &= ~0x08; //清除中断标志位
IICCON |= 0x20; //起始位发送起始信号
while ((!(IICCON & 0x08)) && (IICSTA != 0x08));
IICCON &= ~0x20; //起始位停止起始信号
IICCON &= ~0x08; //清除中断标志位
IICDAT = PCF8591; //写入器件地址
while (IICSTA != 0x18);
IICCON &= ~0x08; //清除中断标志位
IICDAT = fuc_Add; //写入读地址
while (IICSTA != 0x28);
IICCON &= ~0x08; //清除中断标志位
IICCON |= 0x20; //起始位发送起始信号
while ((!(IICCON & 0x08)) && (IICSTA != 0x08));
IICCON &= ~0x20; //起始位停止起始信号
IICCON &= ~0x08; //清除中断标志位
IICDAT = PCF8591 | 0x01; //写入读指令
while (IICSTA != 0x40);
IICCON &= ~0x08; //清除中断标志位
while (IICSTA != 0x58);
fuc_Dat = IICDAT; //读入数据
IICCON &= ~0x08; //清除中断标志位
IICCON |= 0x10; //停止位发送停止信号
return fuc_Dat;
}
/*******************************************************************
DAC 变换, 转化函数
*******************************************************************/
//bit DACconversion(unsigned char sla,unsigned char c, unsigned char Val)
//{
// Start_I2c(); //启动总线
// SendByte(sla); //发送器件地址
// if(ack==0)return(0);
// SendByte(c); //发送控制字节
// if(ack==0)return(0);
// SendByte(Val); //发送DAC的数值
// if(ack==0)return(0);
// Stop_I2c(); //结束总线
// return(1);
//}
//
///*******************************************************************
//ADC发送字节[命令]数据函数
//*******************************************************************/
bit ISendByte(unsigned char sla,unsigned char c)
{
Start_I2c(); //启动总线
SendByte(sla); //发送器件地址
if(ack==0)return(0);
SendByte(c); //发送数据
if(ack==0)return(0);
Stop_I2c(); //结束总线
return(1);
}
/*******************************************************************
ADC读字节数据函数
*******************************************************************/
unsigned char IRcvByte(unsigned char sla)
{ unsigned char c;
Start_I2c(); //启动总线
SendByte(sla+1); //发送器件地址
if(ack==0)return(0);
c=RcvByte(); //读取数据0
Ack_I2c(1); //发送非就答位
Stop_I2c(); //结束总线
return(c);
}
/***************************************************************************************
* @实现效果 UART1接收到上位机发送的数据后,把接收的数据再次发送给上位机
* @注意 波特率1200,8位数据,无校验位
***************************************************************************************/
void main(void)
{
uint8_t bai,shi,ge;
uint16_t i;
/********************************系统初始化*******************************************/
WDTCCR = 0x00; //关闭看门狗
//本例程为方便测试关闭看门狗,实际使用中,建议客户打开看门狗,详见WDT复位例程
CLKCON = 0x02; //选择内部高频RC为系统时钟,Fosc=32MHz
CLKDIV = 0x02; //Fosc 2分频得到Fper,Fper=16MHz
/**********************************IO配置初始化**************************************/
P2M2 = P2M2&0x0F|0x20; //P25设置为上拉输入
P2M2 = P2M2&0xF0|0x08; //P24设置为推挽输出
P0M0 = P0M0 & 0xF0 | 0x0A; //P00带上拉开漏输出
P0M0 = P0M0 & 0x0F | 0x80; //P01推挽输出
SCL_MAP = 0x01; //SCL映射P01口
SDA_MAP = 0x00; //SDA映射P00口
IICCON = 0x40; //启动IIC模块
/**********************************UART配置初始化**************************************/
TXD_MAP = 0x14; //TXD映射P24
RXD_MAP = 0x15; //RXD映射P25
//8位数据发送,波特率1200
//波特率计算
//波特率 = 1/16 * 时钟源频率 / (65536 - 0xFCBE)
// = 1/16 * 16000000 / 834)
// = 1199.04(误差0.05%)
//波特率1200
//反推初值
//初值 = (65536 - (Fper / 波特率) * (1 / 16))
// = (65536 - (16000000 / 1200) * (1 / 16))
// = (65536 - 833.33)
// = FCBE
SBRTH = 0xFCBE/256;
SBRTL = 0xFCBE%256;
SCON2 = 0x12; //8位UART 独立波特率,波特率可变
SCON = 0x10; //开串口接收
//IE = 0x10; //使能串口中断
//EA = 1; //使能总中断
while(1)
{
// if(guc_Uartflag)
// {
// IE &=~ 0x10; //失能UART1中断
// for(guc_i= 0;guc_i<guc_Uartcnt;guc_i++)
// {
// SBUF = guc_Uartbuf_a[guc_i]; //发送数据
// while(!(SCON&0x02));
// SCON &=~ 0x02; //发送中断请求中断标志位清0
// }
// guc_Uartflag = 0; //标志位置0
// guc_Uartcnt = 0;
// SCON |= 0x10; //使能串口中断
// IE |= 0x10; //UART1中断使能
// }
DACconversion(0x40,DAC_VALUE);
DAC_VALUE+=5;
delay(200);
//ISendByte(PCF8591,0x40);
ADCVALUE=ADC(0x40); //ADC0 模数转换1 光敏电阻
// ISendByte(PCF8591,0x40);
// ADCVALUE=IRcvByte(PCF8591); //ADC0 模数转换1 光敏电阻
bai=ADCVALUE/100+0x30;
shi=ADCVALUE%100/10+0x30;
ge=ADCVALUE%10+0x30;
txBuf[11]=bai;
txBuf[12]=shi;
txBuf[13]=ge;
for(i = 0; i < sizeof(txBuf); i++)
{
SBUF = txBuf[i]; //发送数据
while(!(SCON&0x02));
SCON &=~ 0x02; //发送中断请求中断标志位?
}
delay(200);
// for(i=0;i<50000;i++);
}
}
/***************************************************************************************
* @说明 UART1中断服务函数
* @参数 无
* @返回值 无
* @注 无
***************************************************************************************/
void delay(volatile uchar i)
{
volatile uchar j,k;
for(j=i;j>0;j--)
for(k=125;k>0;k--);
}
效果图:
|