完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
本程序是stm32f103 接pcf8591AD/DA板(YL-PCF8591),I2C通信,I2C通信用的是模拟I2C,不是STM32 自带的硬件I2C外设。实践检验很稳定。SCL接口用PB6,SDA用PB7,与STM32自带的硬件I2C接口针脚是一样的,这是巧合,你也可以随便定义成别Pin针脚。关于GPIO设置,最后有解释。 Pcf8591地址写是0x90,读是0x91, AIN0地址是0x40 -------AIN3地址是0x43,注意AOUT地址也是0x40 写比较简单看下面程序:下面是DA(数/模转换主程序)主要用写函数。 u8 DACconversion(u8 sla,u8 c, u8 Val) { Start_I2c(); //启动总线 SendByte(sla); //发送器件地址 ack(); //8591应答 SendByte(c); //发送控制字节 ack(); //8591应答 SendByte(Val); //发送DAC的数值 ack(); //8591应答 Stop_I2c(); //结束总线 return(1); } 启动:SCL高电平中间SDA高变低,紧接着SCL变低, 停止:SCL低电平变高电平后,SDA低变高, Ack应答是主机释放SDA后,从机(PCF8591把SDA拉低)。 DA转换的过程是,先开始,发送从机地址90,从机应答后,发送寄存器地址,40代表AIN0(AOUT也是40 ),从机应答后,发送写入的数据,从机应答,结束传输。 是不是很简单?DOUT输出电压范围(0-255对应0-3.3v )输出接口接有蓝色LED,输出电压大于2V,LED 开始亮起了,电压越高,越亮。 ----------------------------------------------------------------------------------------------/ 下面说明读数据程序,稍微复杂一点。 u8 ADCconversion(u8 sla,u8 c) { u8 d; Start_I2c(); //启动总线 SendByte(sla); //发送器件地址0x90 ack(); //从机接收后应达 SendByte(c); //发送控制字节0x43 ack(); //从机接收后应达 Stop_I2c(); //停止总线 //------------------------------------------------ Start_I2c(); //启动总线 SendByte(sla+1); //发送读AIN3指令 ack(); //从机应对不能少 d=RcvByte(); //发送DAC的数值 Ack_I2c(0); //主机接收后应答不能少否则不稳定 Stop_I2c(); //结束总线 return(d); } 我们读取第4个AIN口因为接有可变电阻,可以直观看到输入数据变化,AIN3地址是0x43(第一个是光敏)(第二个是热敏)(第三个是直通) 下面分析程序,下面是AD转换,接收第四个AIN的电压信号,0-3.3V对应数字0-255: AD起始的程序和DA相同,开始-发送从站地址90,从站应答,发送控制字43,从站应答,之后的程序就不一样的,停止 再次开始,发送读指令91,从站应答,主机读8位数据,读到后主机应答0,表示接受到,最后停止传输。(注意没有这个主机接收应答,接收到数据就乱了在数据和255之间乱跳)。 可以看到Ad转换开始停止两次。特别注意,主机接收到数据后,主机回复Ack(0)。不是从机。 ///------------------------------------------------------------------------------------------------/// 最后说一下关于:IIC的GPIO设置。 void GPIO_init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); GPIO_InitStructure.GPIO_Pin = SCL_Pin | SDA_Pin; /*初始化IO*/ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); SCL_SET(1); flash(); SDA_SET(1); flash(); } 这是GPIO初始化程序,可见GPIO设置为推挽输出,这样I2C的波形用示波器观察就是正经的方波,但是推挽输出只能写数据,I2C读数据的时候必须用in_floating,见下面: void SDA_IO_IN(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); GPIO_InitStructure.GPIO_Pin = SDA_Pin; /*初始化IO*/ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOB, &GPIO_InitStructure); } void SDA_IO_OUT(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); GPIO_InitStructure.GPIO_Pin = SDA_Pin; /*初始化IO*/ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); } 上面程序可见,SCL(PB6)是主机主导,所以一般设为PP不变(推挽输出),SDA因为读到时候是从机发数据,所以对于SDA(PB7)脚,在写数据时候设置成PP(推挽输出),在读入数据时设置成in_floating。这样的波形很漂亮的方波,用示波器观察很爽,逻辑清晰可见。 也有的程序SCL SDA 都设置成OD(开漏输出)不变,这就不用设置变来变去,也是可以的,就是观察波形的时候,波形底部是方波(因为漏极有场效应管通断),波形上部就是三角锯齿波了,(因为没有上场效应管控制,高电位是靠上拉电阻)。这种设置也是可以用,还简单,就是不利于用示波器观察。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1780 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1621 浏览 1 评论
1081 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
728 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1679 浏览 2 评论
1938浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
731浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
570浏览 3评论
596浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
556浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-24 00:00 , Processed in 0.888252 second(s), Total 78, Slave 61 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号