一、说明
首先非常感谢这位博主提供的帮助@u俺的me-CSDN博客,他写的关于TTP229触摸按键的文章直入主题,帮我规避了很多陷阱,让我少走了很多弯路。
二、TTP229-BSF模块使用
TTP229触摸按键是一个系列的全称,我们在使用时一定先注意具体型号,请参考我上文提到的博主的这边文章:触摸IC TTP229学习笔记-CSDN博客。我这里使用到的是TTP229-BSF,模块的配置和使用在数据手册里面有详细的说明,这里我将正确的数据手册贴出来供大家参考(我是将按键模块配置为16键输入、使用串行输出的模式来进行使用的,因此我把关于这种模式配置的关键信息在数据手册里面进行了高亮,便于大家快速阅读)。【免费】TTP229-BSF数据手册资源-CSDN文库
通过阅读数据手册可以知道:16键输入、串行输出模式需要将TP1和TP2通过大电阻接到数字地(用跳线帽按照图示将引脚打通)。
三、Verilog源码与仿真
TTP229-BSF驱动如下:(第一次发文章,没找到Verilog高亮选项,抱歉)
module ttp229bsf_drive(
input i_clk ,
input i_rst_n ,
input i_SDO ,
output o_SCL ,
output [ 15:0] o_key_data ,
output o_key_data_valid
);
localparam P_CNT_TW = 500 ;//15us
localparam P_SYSTEM_CLK = 33_333_333 ;
localparam P_TTP229_FREQ = 500_000 ;//FREQ: 1KHz ~ 512KHz
localparam P_CLK_PERIOD = P_SYSTEM_CLK/P_TTP229_FREQ;
localparam P_CNT_TOUT = 66_666 ;
reg r_SDO_0d ;
reg r_SDO_1d ;
reg [ 15:0] r_Tw_cnt ;
reg [ 15:0] r_DV_cnt ;
reg r_Tw_cnt_en ;
reg r_SCL_cnt_en ;
reg [ 15:0] r_SCL_cnt ;
reg r_SCL ;
reg [ 7:0] r_bit_cnt ;
reg [ 15:0] r_key_data ;
reg r_key_data_valid ;
reg [ 15:0] r_Tout_cnt1 ;
reg [ 15:0] r_Tout_cnt2 ;
reg r_finish_flag ;
wire w_pose_SDO ;
wire w_nege_SDO ;
assign w_pose_SDO = r_SDO_0d && (!r_SDO_1d);
assign w_nege_SDO = (!r_SDO_0d) && r_SDO_1d;
assign o_SCL = r_SCL;
assign o_key_data = r_key_data;
assign o_key_data_valid = r_key_data_valid;
//i_SDO打一拍
always@(posedge i_clk, negedge i_rst_n)begin
if(~i_rst_n)begin
r_SDO_0d <= 'd0;
r_SDO_1d <= 'd0;
end
else begin
r_SDO_0d <= i_SDO;
r_SDO_1d <= r_SDO_0d;
end
end
//r_DV_cnt
always@(posedge i_clk, negedge i_rst_n)begin
if(~i_rst_n)
r_DV_cnt <= 'd0;
else if(w_nege_SDO)
r_DV_cnt <= 'd0;
else if(w_pose_SDO || r_DV_cnt >= 'd1)
r_DV_cnt <= r_DV_cnt + 'd1;
else
r_DV_cnt <= 'd0;
end
//Tw延时计数器使能
always@(posedge i_clk, negedge i_rst_n)begin
if(~i_rst_n)
r_Tw_cnt_en <= 'd0;
else if(w_nege_SDO && r_DV_cnt == (P_CLK_PERIOD - 'd1))
r_Tw_cnt_en <= 'd0;
else if(w_nege_SDO && r_DV_cnt != (P_CLK_PERIOD - 'd1))
r_Tw_cnt_en <= 'd1;
else if(r_Tw_cnt == P_CNT_TW - 'd1)
r_Tw_cnt_en <= 'd0;
else
r_Tw_cnt_en <= r_Tw_cnt_en;
end
//Tw延时计数器
always@(posedge i_clk, negedge i_rst_n)begin
if(~i_rst_n)
r_Tw_cnt <= 'd0;
else if(r_Tw_cnt == P_CNT_TW - 'd1)
r_Tw_cnt <= 'd0;
else if(r_Tw_cnt_en)
r_Tw_cnt <= r_Tw_cnt + 'd1;
else
r_Tw_cnt <= r_Tw_cnt;
end
//SCL计数器使能
always@(posedge i_clk, negedge i_rst_n)begin
if(~i_rst_n)
r_SCL_cnt_en <= 'd0;
else if(r_Tw_cnt == P_CNT_TW - 'd1)
r_SCL_cnt_en <= 'd1;
else if(r_bit_cnt == 'd15 && r_SCL_cnt == (P_CLK_PERIOD - 'd1) >> 'd1)
r_SCL_cnt_en <= 'd0;
else
r_SCL_cnt_en <= r_SCL_cnt_en;
end
//SCL计数器
always@(posedge i_clk, negedge i_rst_n)begin
if(~i_rst_n)
r_SCL_cnt <= 'd0;
else if(r_SCL_cnt == P_CLK_PERIOD - 'd1)
r_SCL_cnt <= 'd0;
else if(r_SCL_cnt_en)
r_SCL_cnt <= r_SCL_cnt + 'd1;
else
r_SCL_cnt <= 'd0;
end
//SCL(0 ~ 332)
always@(posedge i_clk, negedge i_rst_n)begin
if(~i_rst_n)
r_SCL <= 'd0;
else if(r_Tw_cnt == P_CNT_TW - 'd1)
r_SCL <= ~r_SCL;
else if(r_SCL_cnt == (P_CLK_PERIOD - 'd1) >> 'd1)
r_SCL <= ~r_SCL;
else if(r_SCL_cnt == P_CLK_PERIOD - 'd1)
r_SCL <= ~r_SCL;
else
r_SCL <= r_SCL;
end
//bit_cnt
always@(posedge i_clk, negedge i_rst_n)begin
if(~i_rst_n)
r_bit_cnt <= 'd0;
else if(r_bit_cnt == 'd15 && (r_SCL_cnt == P_CLK_PERIOD - 'd1))
r_bit_cnt <= 'd0;
else if(r_SCL_cnt == P_CLK_PERIOD - 'd1)
r_bit_cnt <= r_bit_cnt + 'd1;
else if(r_finish_flag)
r_bit_cnt <= 'd0;
else
r_bit_cnt <= r_bit_cnt;
end
//按键数据
always@(posedge i_clk, negedge i_rst_n)begin
if(~i_rst_n)
r_key_data <= 'd0;
else if(r_bit_cnt == 'd0)
r_key_data[r_bit_cnt] <= i_SDO;
else if(r_bit_cnt >= 'd1)
r_key_data[r_bit_cnt] <= r_SDO_1d;
else
r_key_data <= r_key_data;
end
//按键数据有效
always@(posedge i_clk, negedge i_rst_n)begin
if(~i_rst_n)
r_key_data_valid <= 'd0;
else if(r_bit_cnt == 'd15 && r_SCL_cnt == (P_CLK_PERIOD - 'd1) >> 'd1)
r_key_data_valid <= 'd1;
else if(r_Tw_cnt_en)
r_key_data_valid <= 'd0;
else
r_key_data_valid <= r_key_data_valid;
end
//Tout
always@(posedge i_clk, negedge i_rst_n)begin
if(~i_rst_n)
r_Tout_cnt1 <= 'd0;
else if(r_Tout_cnt1 == (P_CNT_TOUT >> 1) - 'd1)
r_Tout_cnt1 <= 'd0;
else if(r_key_data_valid)
r_Tout_cnt1 <= r_Tout_cnt1 + 'd1;
else
r_Tout_cnt1 <= r_Tout_cnt1;
end
always@(posedge i_clk, negedge i_rst_n)begin
if(~i_rst_n)
r_Tout_cnt2 <= 'd0;
else if(r_Tout_cnt2 == 'd1 && r_Tout_cnt1 == (P_CNT_TOUT >> 1) - 'd1)
r_Tout_cnt2 <= 'd0;
else if(r_Tout_cnt1 == ((P_CNT_TOUT >> 1) - 'd1))
r_Tout_cnt2 <= r_Tout_cnt2 + 'd1;
else
r_Tout_cnt2 <= r_Tout_cnt2;
end
//finish_flag
always@(posedge i_clk, negedge i_rst_n)begin
if(~i_rst_n)
r_finish_flag <= 'd0;
else if(r_Tout_cnt2 == 'd1 && r_Tout_cnt1 == ((P_CNT_TOUT >> 1) - 'd1))
r_finish_flag <= 'd1;
else
r_finish_flag <= 'd0;
end
endmodule
Vivado仿真:
四、结束语
小编最后用TTP229-BSF驱动输出的按键数据(o_key_data)去点灯了。虽然仿真和最终的实验现象正确,但驱动代码难免还有不周的地方,欢迎各位朋友指正与交流。