python控制单⽚机keil_PCF8591使⽤及Python控制
PCF8591使⽤及Python控制
INTRODUCTION
⼤家⼀定对于PCF8591芯⽚,对于其中的A0、A1、A2、channel0-channel3、AIN0-AIN3、AOUT、SCL、SDA等等以及I2C协议有
着很⼤的困惑。同时也没有完全理解Python代码中的0x40、0x41、0x42、0x43、0x48到底是什么,_byte(0x48,0x40)
_byte(0x48,0x40,value)_byte(0x48)这些代码到底控制什么。
这篇⽂章将帮助⼤家理清以上内容。
⼀、PCF8591与RaspberryPi的关系
做⼀个很简单的形象化,将整个系统看作⼀个进⽔/出⽔装置。
装置有四根进⽔管,分别命名为AIN0,AIN1,AIN2,AIN3,还有唯⼀⼀根出⽔管,命名为AOUT。还有四个中转通道,分别命名为
channel0,channel1,channel2,channel3,从四根进⽔管进来的⽔可以受控制地从某⼀个通道中流出,进⼊总管道,之后通过两根出⽔
管道——SDA和SCL,进⼊⼀个⽔的加⼯处理储存设备。
RaspberryPI是“MASTER”,PCF是“SLAVER”,他们之间是主从关系。如果主器件要发送数据给从器件,则会启动数据传输,并发
送数据⾄从器件,最后终⽌数据传输;如果主器件想要接受从器件发来的数据,同样也是发出命令启动数据传输,接收从器件发来的数据,
最后终⽌接收过程。
强调⼀点:每次数据传输都是由“MASTER”主动开启的。
是否清晰了⼀些?理清总的关系以后我们再来看具体细节。
⼆、PCF的地址与A0-A2引脚
⼀个“MASTER”不可能只有⼀个“SLAVER”。所以对于“MASTER”来说,需要给“SLAVERS”编号,以便控制、命令。这个编号
也就是PCF地址。地址的编码规则如下图:
可以看出,这是⼀个七位⼆进制数,前四位是fixednumber,后三位分别对应PCF的三个引脚——A0,A1,A2。每⼀个引脚的值都可以是
0或1,⼀共2^3=8种排列⽅式,也即⼀共8个可使⽤的地址。所以⼀个“MASTER”最多能同时控制8个“SLAVER”。对于PCF8591
来说,其defaultaddress为0x48(⼗六进制数),转换为⼆进制数是1001000,所以可以知道他的A0、A1、A2三个引脚值均为0。
需要再提前强调⼀点,Python代码中所有0x⼗六进制数,只有0x48代表Address,也只有PCF拥有Address,其余所有⼗六进制数都不
代表Address。(这是⼀个天坑)
三、I2C协议与SDASCL
“MASTER”与“SLAVERS”之间需要有沟通交流,给“SLAVER”分配⼯作或是让“SLAVER”汇报⼯作,并告知“SLAVER”如何
做。所以他们之间有⼀个特定的沟通⽅式,这个沟通⽅式就叫I^2C通信协议(Inter-IntegratedCircuit)。I^2C总线需要两根线来实现连接
于总线上的器件之间的信息传输,⼀根是SDA(SerialData)串⾏数据线,另⼀根是SCL(SerialClock)串⾏时钟线。
下图是ADconvert的I2C数据传输流程。
是不是很令⼈迷惑?没关系,形象化的解释来了。之前有说过,I2C就是⼀种沟通⽅式,所以这个数据传输流程,就可以理解为在I2C这种
特定沟通⽅式下的⼀次沟通。讲的更通俗⼀点,就是⼀次聊天对话。如何理解?
聊天的第⼀步,是拿出⼿机打开微信。(对应STARTcondition,当SDA和SCL两条线的电平同时满⾜某⼀特定条件时,传输开始。)
打开微信后需要找⼀个联系⼈才能聊天,我们之前说“MASTER”有很多“SLAVERS”,这⼀步便是“MASTER”选择与某⼀
个“SLAVER”对话。(对应ADDRESS。)
第三步,“MASTER”确定这次对话的⽬的的给“SLAVER”分配活⼉⼲,还是让“SLAVER”⼲完活后汇报。(对应R/W,Rmeans
read,Wmeanswrite,控制这次数据传输的⽬的是树莓派写⼊⼀个值到PCF中,还是树莓派从PCF中读取⼀个值。)
可以看到有很多ACK。ACKmeansAcknowledgecharacter,即确认字符,意思是数据接收者告诉数据传输者,“已收到”。
之后便是数据传输,每传输⼀个byte的数据,都会反馈⼀个ACK确认数据收到。
四、Python代码控制读取/写⼊值
importsmbus
importtime
if__name__=="__main__":
bus=(1)
_byte(0x48,0x42)
_byte(0x48)
whileTrue:
num=_byte(0x48)
print(num)
_byte_data(0x48,0x42,160)
(0.01)
其实代码⾮常简单。之前参考⽂献给出的代码令⼈迷惑的原因主要是⾃定义了很多⽅法。现在⽤最简单的办法写出来,⽤到的核⼼⽅法只有
三个:
_byte(ADDRESS)
_byte(ADDRESS,CONTROL_byte)
_byte_data(ADDRESS,CONTROL_byte,value)
顾名思义,read_byte就是从PCF中读取⼀个byte的数据,write_byte就是向PCF中写⼊⼀个byte的数据,write_byte_data就是像PCF中
写⼊data。
有⼈就会问了,write_byte和write_byte_data有什么区别?
还记得在PART1中强调的点吗?每次数据传输⼀定是由“MASTER”主动开启的,所以write_byte的⽬的是明确“MASTER”与哪
个“SLAVER”对话,建⽴联系,并以⼀个“CONTROLbyte”告知“SLAVER”如何⼯作,并不传输value。这也是为什么代码中的第
⼀步是_byte(0x48)
树莓派主动开启对话,与0x48地址对应的PCF8591建⽴联系,并通过⼀个CONTROLbyte明确⼯作模式(AnalogInputMode)。
第⼆个问题来了,CONTROLbyte是什么?那不是个地址吗?
这时候应该要想起PART2强调的内容(只有0x48是地址)。write_byte⽅法的第⼆个传参是⼀个CONTROLbyte。
这是官⽅⽂档对于CONTROLbyte的解释。8位⼆进制码,其中第⼀位和第五位都是fixednumber—0,可被编写的部分是第⼆位——代
表是否开启AOUT输出⼝,0表⽰不开启,1表⽰开启,只有该位是1的时候,DA才会⼯作,数字信号被转为模拟信号从AOUT端⼝输出;
第三四位——代表四种不同的analoginputmode,⽤以明确AIN端⼝与channel之间的数据关系。
在第⼀幅图中有⼀个⼤⼤的问号,analoginputmode便是明确这个问号。有两种对应关系:⼀种是single-ended,即⼀对⼀。例如在00
模式下,从channel0中读到的数据就是AIN0⼝输⼊的模拟量经过AD转换后的数字值,00模式的四个AIN端⼝都是分别⼀⼀对应于⼀个
channel;在10模式下,AIN0和AIN1是⼀⼀对应channel0和channel1。另外⼀种对应关系是differential,即差分。例如在01模式
下,channel0的值是AIN0与AIN3的差值;在10模式下,channel2的值是AIN2与AIN3的差值。
CONTROLbyte的第七⼋位是ADchannelnumber,⽤来控制从哪个channel读取数据。第六位是auto-increment,值为1时,每次读
取数据都会⾃动切换channel,第⼀次读channel0的数据,下⼀次读到的就是channel1的数据,以此类推。
在Python代码中,CONTROLbyte是⼀个⼗六进制数,转换为⼆进制后就是⼋位⼆进制。控制⽅法为:确定CONTROLbyte中可编码位
上你想要的取值,得到⼀个⼋位⼆进制数,转为⼗六进制数,输⼊Python⽅法。
讲到这⾥后就⼏乎结束了⼤部分的内容。继续代码⽰例,read_byte,读值过程不需要CONTROLbyte,所以传参只有ADDRESS。
可以看到,在真正读取想要的num之前,还有⼀次空读。这是因为PCF8591在接到读取命令后,同时进⾏上⼀次的转换数据的传输及本次
的数据转换,所以第⼀次空读的数据是⼀个不确定的数,第⼀次的空读只是为了启动下⼀次正常的读取。
_byte_data(0x48,0x42,160)
write_byte_data这个⽅法再多解释⼀下,写⼊的值会直接作为⼀个digitalvalue,经过转换后以电压形式的模拟量从AOUT⼝输出。我们
使⽤的PCF8591是⼀个8bits的AD/DA转换器,8bits的意思是AD/DA共有2^8=256个刻度,所以传输的digital值范围是0-255。举个
例⼦,你希望从AOUT⼝输出⼀个3.13V的电压给LED灯,应该写⼊的值为3.13v/5v*255=160(这⾥ADC接5v的基准电压),但是实际上
⽤电压表测得此时LED灯两端电压为2.64v,与理想值有⼀定误差。
五、SomethingMore
我⼏乎尝试了所有的analoginputmode,将麦克风接⼊不同的AIN⼝,选择不同的channel,⽤⽰波器/电压表+python画出的图进⾏了
很多很多实验,在差分模式下还是有很多难以解释的试验现象,但是基本可以肯定整个原理是没有错的。
补充⼀点,single-ended模式下,AD转换的模拟量就是该AIN⼝与GND的电压;differential模式下,AD转换的模拟量则是两个AIN⼝之
间的电压差,所以如果只使⽤⼀个AIN⼝且还想要⽤差分模式,那么另⼀个AIN⼝要记着接地。
六、LearningExperience
本次超过30个⼩时的学习过程得到的经验:
①永远不要认为你之前的理解都是对的。发现整个理解过程出现错误,有时候有必要推倒重建。
②⽹上资料参差不齐,错误百出,绝对不能盲⽬相信。
③实验要清楚记录条件及现象,不然会因为没记清现象/条件⽽做很多次重复实验。
④在学习⼀个全新的知识系统的过程中会有很多信息涌⼊,往往在查找资料解决问题1的时候会发现问题2,然后注意⼒转移到问题2上,之
后⼜会发现新的问题,进⼊⼀个死循环。所以需要适时停⽌,思考⼀下你是谁,你在哪⼉,你要⼲什么。
⑤把问题记录下来,然后接着探索。很有可能在第⼆天的时候你回看第⼀天的问题,会发出感叹:我怎么会问这么愚蠢的问题。
⑥队友很重要。讨论/⽌损/提问/复盘/总结。
我的第⼀篇CSDN博客,希望讲的清楚。希望⼤家喜欢!!
本文发布于:2022-12-31 22:07:55,感谢您对本站的认可!
本文链接:http://www.wtabcd.cn/fanwen/fan/90/68117.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |