打印
[通用8051核FLASH系列]

【芯圣电子HC89S105A测评报告】+PCF8591DAC

[复制链接]
2362|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 芯圣电子官方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--);
}
效果图:

使用特权

评论回复
沙发
有何不可0365| | 2024-7-31 14:45 | 只看该作者
在 ADC 函数中,你需要指定要读取的 ADC 通道。根据 PCF8591 的工作原理,读取 ADC 时需要首先选择 ADC 通道(如 A0、A1、A2、A3)。在你的代码中,fuc_Add 可能是选择 ADC 通道的控制字节。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

467

主题

3517

帖子

7

粉丝