完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
*****以下代码来源于清翔电子教程******
问题1:I2C为什么要初始化呢?感觉不初始化得到的也是一样的结果啊 描述:I2C总线初始化 ====================================*/ void I2C_init() { SDA = 1; //数据总线高 _nop_(); SCL = 1; //时钟总线高 _nop_(); } 问题2: I2C的停止信号函数为什么要先把数据总线SDA拉低呢 描述:I2C停止信号 ====================================*/ void I2C_Stop() { SDA = 0; _nop_(); SCL = 1; Delay5us(); SDA = 1; Delay5us(); } 问题3:I2C主机发送应答函数为什么最后要拉高数据总线呢?那个释放SDA又是什么意思 描述:I2C主机发送应答 ====================================*/ void Master_ACK(bit i) { SCL = 0; // 拉低时钟总线允许SDA数据总线上的数据变化 _nop_(); // 让总线稳定 if (i) //如果i = 1 那么拉低数据总线 表示主机应答 { SDA = 0; } else { SDA = 1; //发送非应答 } _nop_();//让总线稳定 SCL = 1;//拉高时钟总线 让从机从SDA线上读走 主机的应答信号 Delay5us(); SCL = 0;//拉低时钟总线, 占用总线继续通信 _nop_(); SDA = 1;//释放SDA数据总线。 _nop_(); } 问题4: 检测到从机非应答或者非应答后为什么要把SCL拉低呢(代码中标有问题4处) 描述:I2C检测从机应答 ====================================*/ bit Test_ACK() // 检测从机应答 { SCL = 1;//时钟总线为高电平期间可以读取从机应答信号 Delay5us(); if (SDA) { SCL = 0; //问题4 I2C_Stop(); return(0); } else { SCL = 0; return(1); } } 还有为什么在这个AD—DA转换代码中,数码管显示转换过来的数字量不会随光照的变化而变化呢,用LED检测I2C读写结果都没有问题。 #include #include #define MAIN_Fosc 11059200UL //宏定义主时钟HZ #define PCF8591_ADDR 0x90 //PCF8591地址 #define DACOUT_EN 0x40 //DAC输出使能 /*==================================== 自定义类型名 ====================================*/ typedef unsigned char INT8U; typedef unsigned char uchar; typedef unsigned int INT16U; typedef unsigned int uint; /*==================================== 硬件接口位声明 ====================================*/ ***it SDA = P2^0; //I2C串行数据 ***it SCL = P2^1; //I2C串行时钟 ***it DU = P2^6; //数码管段选 ***it WE = P2^7; //数码管位选 ***it LED1= P1^0; //读取AD的值是否成功(亮成功,灭失败) ***it LED2= P1^1; //DAC成功输出(亮成功,灭失败) ***it BEEP= P2^3; //蜂鸣器引脚定义 uchar AD_Value; //存储AD转换回的数字量 /*==================================== 共阴极数码管段选码 ====================================*/ 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() { SCL = 1; _nop_(); SDA = 1; Delay5us(); SDA = 0; Delay5us(); } /*==================================== 函数:I2C_Stop() 描述:I2C停止信号 ====================================*/ 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线上读走 主机的应答信号 Delay5us(); 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输出*/ bit DAC_OUT(uchar DAT) { I2C_Start(); I2C_send_byte(PCF8591_ADDR+0); if (!Test_ACK()) { return(0); } I2C_send_byte(DACOUT_EN); //DA输出使能 if (!Test_ACK()) { return(0); } I2C_send_byte(DAT); if (!Test_ACK()) { return(0); } I2C_Stop(); return(1); } /*读AD数据*/ bit ADC_Read(uchar CON) { I2C_Start(); I2C_send_byte(PCF8591_ADDR+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); } AD_Value = I2C_read_byte(); Master_ACK(0); I2C_Stop(); return(1); } void main() { I2C_init(); while(1) { //单端输入,读出通道2的值 if (ADC_Read(0x02)) LED1 = 0; else LED1 = 1; if (DAC_OUT(AD_Value)) LED2 = 0; else LED2 = 1; Display(AD_Value); if (AD_Value > 150) BEEP = 0; else BEEP = 1; Delay_Ms(5); } } |
|
相关推荐
4个回答
|
|
根据iic的时序图看看,结果没变化就要一点一点查程序验证了,当然要确保硬件没问题。
|
|
|
|
I2C的要求
|
|
|
|
问题 1: 初始化总线给高电频和你不初始化一样 是因为你的单片机上电引脚就是高电频,万一你用其他上电单片机是低电频的话就不合适了
|
|
|
|
首先帮你屡一下思路:1,你是用I2C去采集,2将采集的值在用I2C输出,3,显示输出的值。是采集问题还是输出问题还是显示问题。这样顺着这思路走
|
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
503 浏览 0 评论
求助一下关于51系列单片机的Timer0的计时问题,TH0、TL0+1的时间是怎么算的?
1756 浏览 1 评论
【RA-Eco-RA4E2-64PIN-V1.0开发板试用】开箱+Keil环境搭建+点灯+点亮OLED
1183 浏览 0 评论
【敏矽微ME32G070开发板免费体验】使用coremark测试敏矽微ME32G070 跑分
1053 浏览 0 评论
【敏矽微ME32G070开发板免费体验】开箱+点灯+点亮OLED
1287 浏览 2 评论
【youyeetoo X1 windows 开发板体验】少儿AI智能STEAM积木平台
12022 浏览 31 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-23 19:34 , Processed in 0.638971 second(s), Total 75, Slave 59 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号