设计基础
pca9685的舵机控制
Verilog实现IIC主机对从机的写操作(zybo z7板运行代码)
模块说明
模块框图
参数解释
输入信号:
word[15:0]——输入理想的舵机角度
write[2:0]——输入指定转动的舵机序号
start——传输信号开始
initialize——重置所有舵机角度
输出信号:
SDA——IIC数据线
SCL——IIC时钟线
模块详解
IIC_SEND模块的主要功能为将接受到的并行8位数据信号,寄存器地址信号转为串行方式输出,同时在一次传输结束之后发送O_done_flag信号,告知控制模块一次发送完成。
Control_setPWM模块的主要功能为接受前一转换器模块发送来的控制信号,进而将16位数据信号转换为高8位和低8位分别发送,同时接受相应的write信号并将其转化为实际的从机的寄存器地址。因为每次改变舵机角度时需要发送4次IIC信号给pca9685驱动板,所以当Control_setPWM收到start信号时,进入一个4状态的有限状态机,在4状态循环内进入下一状态的标志为IIC_SEND完成一次发送的O_done_flag信号,同时在4状态完成时发送done信号代表一次控制命令执行完成。
代码实现
在Verilog实现IIC主机对从机的写操作(zybo z7板运行代码)
这篇博文中已经上传了verilog实现IIC信号传输的代码,所以这里只需要Control_setPWM模块的代码和顶层模块代码就可以实现了
Control_setPWM
//实现setPWM功能
module Control_setPWM(
input O_done_flag,//检测一次IIC传输是否完成
input [2:0]write,//输入地址写入信号(0--3号舵机)
input [15:0]word,//输入16进制下降沿的时间
input start,//开始信号,改变数据后是否开始传输
input rst,
input clk,
input initialize,//初始化信号
output reg [7:0]word_add,//输出寄存器地址
output reg [7:0]data,//输出数据
output reg en,//输出使能信号
output reg done//一次命令传输完成
// output reg [4:0]state//检验输出
);
//variation declaration
reg en_reg,en_next;
reg [4:0]state_reg,state_next;//有限状态机,一共5个状态,1个空闲位,一次发送4个数据
reg [7:0]data_reg,data_next;
reg [7:0]word_add_reg,word_add_next;
reg [15:0]word_reg;//存储输入的下降沿时间
reg done_reg,done_next;
reg [16:0]i_reg,i_next;//循环计数值
parameter ON_L=8'H06;//16进制
parameter ON_H=8'H07;
parameter OFF_L=8'H08;
parameter OFF_H=8'H09;
parameter PCA9685_MODE1=8'H00;//寄存器1地址
parameter PCA9685_PRESCALE=8'HFE;//周期寄存器地址
always@(posedge clk,posedge rst)
if(rst) begin//没有输出数据
state_reg<=0;
data_reg<=0;
word_add_reg<=0;
en_reg<=0;
done_reg<=0;
i_reg=17'b11000011010100000;
// i_reg<=5;
end
else begin
state_reg<=state_next;
data_reg<=data_next;
word_add_reg<=word_add_next;
en_reg<=en_next;
done_reg<=done_next;
i_reg<=i_next;
end
always@*
begin
state_next<=state_reg;
data_next<=data_reg;
word_add_next<=word_add_reg;
en_next<=en_reg;
done_next<=done_reg;
case(state_reg)
0://idle状态,复位所有寄存器,并让使能信号拉低
if(initialize)//当有初始化信号时,优先进入初始化
begin
state_next<=26;//进入初始化状态
// data_next<=8'b00110001;
data_next<=8'b00000000;//1st发送全0信号
word_add_next<=PCA9685_MODE1;//装载MODE1
en_next<=1;
done_next<=0;
end
else//再考虑传输信号
if(start)//传输信号开始
begin
state_next<=1;
word_add_next<=ON_L+4*write;
data_next<=8'H00;//起始信号一直为0
en_