本帖最后由 芯圣电子官方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--);
- }
效果图:
|