ADDA数模转换——PCF8591
2015-08-15 16:53
525 查看
#include <reg52.h> #include <intrins.h> #define MAIN_Fosc 11059200UL //宏定义主时钟HZ #define PCF8591_ADDR 0x90 //PCF8591地址 #define DACOUT_EN 0x40 //DAC输出使能 sbit BEEP = P2^3; //蜂鸣器 /*==================================== 自定义类型名 ====================================*/ typedef unsigned char INT8U; typedef unsigned char uchar; typedef unsigned int INT16U; typedef unsigned int uint; /*==================================== 硬件接口位声明 ====================================*/ sbit SDA = P2^0; //I2C串行数据 sbit SCL = P2^1; //I2C串行时钟 sbit DU = P2^6; //数码管段选 sbit WE = P2^7; //数码管位选 sbit LED1= P1^0; //ADC读取失败指示灯(亮成功,灭失败) sbit LED2= P1^1; //DAC转换失败指示灯(亮成功,灭失败) /*==================================== 共阴极数码管段选码 ====================================*/ uchar code table[]={ //0 1 2 3 4 5 6 7 8 0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, //9 A B C D E F - . 关显示 0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71, 0x40, 0x80, 0x00 }; /*==================================== 数码管位选码 ====================================*/ //第1位 2位 3位 4位 5位 6位 7位 8位 uchar code T_COM[] = {0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f};//数码管位码 /*==================================== 函数:void Delay_Ms(INT16U ms) 参数:ms,毫秒延时形参 描述:12T 51单片机自适应主时钟毫秒级延时函数 ====================================*/ void Delay_Ms(INT16U ms) { INT16U i; do{ i = MAIN_Fosc / 96000; while(--i); //96T per loop }while(--ms); } /*==================================== 函数:void Delay5us() 描述:12T 51单片机5微秒延时函数自适应时钟(11.0592M,12M,22.1184M) ====================================*/ void Delay5us() { #if MAIN_Fosc == 11059200 _nop_(); #elif MAIN_Fosc == 12000000 _nop_() #elif MAIN_Fosc == 22118400 _nop_(); _nop_(); _nop_(); #endif } /*==================================== 函数:void Display(INT8U Value) 参数:Value,显示值 取值0-255 描述:共阴极数码管显示函数可显示一个字节的数 ====================================*/ void Display(INT8U Value) { //------------------------------ DU = 1; P0 = table[Value/100]; //管显示百位 DU = 0; P0 = 0xff; //清除断码 WE = 1; P0 = T_COM[0]; //第一位数码管 WE = 0; Delay_Ms(5); //------------------------------- DU = 1; P0 = table[Value%100/10]; //显示十位 DU = 0; P0 = 0xff; //清除断码 WE = 1; P0 = T_COM[1]; //第二位数码管 WE = 0; Delay_Ms(5); //------------------------------- DU = 1; P0 = table[Value%10]; //显示个位 DU = 0; P0 = 0xff; //清除断码 WE = 1; P0 = T_COM[2]; //第三位数码管 WE = 0; Delay_Ms(5); } /*==================================== 函数:I2C_init() 描述:I2C总线初始化 ====================================*/ void I2C_init() { SDA = 1; //数据总线高 _nop_(); SCL = 1; //时钟总线高 _nop_(); } /*==================================== 函数:I2C_Start() 描述:I2C起始信号 ====================================*/ void I2C_Start() { SDA = 1; _nop_(); SCL = 1; Delay5us(); SDA = 0; Delay5us(); } /*==================================== 函数:I2C_Stop() 描述:I2C停止信号 ====================================*/ 4000 void I2C_Stop() { SDA = 0; _nop_(); SCL = 1; Delay5us(); SDA = 1; Delay5us(); } /*==================================== 函数:Master_ACK(bit i) 参数:i 为0时发送非应答 为1时发送应答 描述:I2C主机发送应答 ====================================*/ void Master_ACK(bit i) { SCL = 0; // 拉低时钟总线允许SDA数据总线上的数据变化 _nop_(); // 让总线稳定 if (i) //如果i = 1 那么拉低数据总线 表示主机应答 { SDA = 0; } else { SDA = 1; //发送非应答 } _nop_();//让总线稳定 SCL = 1;//拉高时钟总线 让从机从SDA线上读走 主机的应答信号 _nop_(); SCL = 0;//拉低时钟总线, 占用总线继续通信 _nop_(); SDA = 1;//释放SDA数据总线。 _nop_(); } /*==================================== 函数:Test_ACK() 返回:0为不应答 1为应答 描述:I2C检测从机应答 ====================================*/ bit Test_ACK() // 检测从机应答 { SCL = 1;//时钟总线为高电平期间可以读取从机应答信号 Delay5us(); if (SDA) { SCL = 0; I2C_Stop(); return(0); } else { SCL = 0; return(1); } } /*==================================== 函数:I2C_send_byte(uchar byte) 参数:byte 要发送的字节 描述:I2C发送一个字节 ====================================*/ void I2C_send_byte(uchar byte) { uchar i; for(i = 0 ; i < 8 ; i++) { SCL = 0; _nop_(); if (byte & 0x80) // { SDA = 1; _nop_(); } else { SDA = 0; _nop_(); } SCL = 1; _nop_(); byte <<= 1; } SCL = 0; _nop_(); SDA = 1; _nop_(); } /*==================================== 函数:I2C_read_byte() 返回:读取的字节 描述:I2C读一个字节 ====================================*/ uchar I2C_read_byte() { uchar i, dat; SCL = 0 ; _nop_(); SDA = 1; _nop_(); for(i = 0 ; i < 8 ; i++) { SCL = 1; _nop_(); dat <<= 1; if (SDA) { dat |= 0x01; } _nop_(); SCL = 0; _nop_(); } return(dat); } /*==================================== 函数:DAC_OUT(uchar DAT) 参数:DAT,发送给PCF8591转换的数字量 返回:返回1执行成功,0失败 描述:主机发送数字量交由PCF8591转换为模拟量 ====================================*/ bit DAC_OUT(uchar DAT) { I2C_Start(); //I2C总线起始 I2C_send_byte(PCF8591_ADDR+0);//发送PCF8591地址加读写方向位0(写) if (!Test_ACK()) //检测是否发送成功(应答) { return(0); } I2C_send_byte(DACOUT_EN); //发送控制字节DAC输出使能 if (!Test_ACK()) //检测是否发送成功(应答) { return(0); } I2C_send_byte(DAT); //发送数字量交由PCF8591转为模拟量AOUT脚输出 if (!Test_ACK()) //检测是否发送成功(应答) { return(0); } I2C_Stop(); //I2C停止信号 return(1); } /*==================================== 函数:bit ADC_Read(uchar CON, uchar *DAT) 参数:CON,ADC控制字节 *DAT指针变量,用于存放带入形参变量的地址 返回:返回1执行成功,0失败 描述:读取PCF8591的转换回的值 ====================================*/ bit ADC_Read(uchar CON, uchar *DAT) { I2C_Start(); //I2C起始信号 I2C_send_byte(PCF8591_ADDR+0); //发送PCF8591地址加读写方向位0(写) if (!Test_ACK()) //检测是否发送成功(应答) { return(0); } I2C_send_byte(CON); //发送控制字节 Master_ACK(0); //发送非应答 I2C_Start(); //重发起始信号 I2C_send_byte(PCF8591_ADDR+1); //改变读写方向(读) if (!Test_ACK()) //检测是否发送成功(应答) { return(0); } *DAT = I2C_read_byte(); //把读取的值赋给形参 Master_ACK(0); //主机发送非应答 I2C_Stop(); //I2C停止信号 return(1); //成功返回1 } /*==================================== 函数:void main() 描述:主函数 ====================================*/ void main() { INT8U ADC_Value; //存放ADC的值 I2C_init(); while(1) { //读取通道2转换的值,单端输入。 if(!ADC_Read(0x02, &ADC_Value)) LED1 = 1; else; LED1 = 0; //把AD转换得的数量在送给PCF8591转为模拟量控制模拟量输出口的小灯 if(!DAC_OUT(ADC_Value)) LED2 = 1; else LED2 = 0; //显示读出的模拟量 Display(ADC_Value); if (ADC_Value > 150) BEEP = 1; else BEEP = 1; Delay_Ms(5); } }
相关文章推荐
- 用MSP430F247硬件IIC控制PCF8591转换模块
- PCF8591
- AD/DA转换
- “远程温度多点温度采集卡”的笔记
- pcf8951 ad/da(iic)转换模块 在 esp8266下的实现
- 树莓3b adc模块pcf8591
- I2C协议详解
- protues仿真之数码管消影问题
- 树莓派用Python写几个简单程序5:用socket传图像
- High Performance Browser Networking - TCP UDP TLS
- 12、SQL Server 行列转换
- 2013-3 阿里性能稳定性沙龙
- 手机网页Html代码实现(解决显示页面很小的问题)
- Linux 邮件服务器原理介绍,编译安装Postfix实现本地的邮件服务。
- Linux 邮件服务器原理介绍,编译安装Postfix实现本地的邮件服务。
- 4 Values whose Sum is 0
- STM32——GPIO之从库函数到寄存器的前因后果
- STM32——GPIO之从库函数到寄存器的前因后果
- bimap OOM(2)
- linux添加头文件路径