2.2. 键盘工作简析
2.2.1. 工作流程
1) 默认:
Row[3:0]为输入,默认为4'b1111,因为电阻上拉
Col[3:0]为输出,默认输出4'b0000,保证按键按下时电流流向Col[3:0]
2) 当某一按键按下时,电流流向Col[x]=1,相应Row[x]=0
3) 通过循环Col键值扫描,代码如下:
case(next_state) SCAN_IDLE : begin col_data <= 4'b0000; //ensure current can flow when key is down row_data_r <= 4'b0000; col_data_r <= 4'b0000; end //SCAN_JITTER1: SCAN_COL0 : col_data <= 4'b1110; //scan the 1th row if the key is down SCAN_COL1 : col_data <= 4'b1101; //scan the 2th row if the key is down SCAN_COL2 : col_data <= 4'b1011; //scan the 3th row if the key is down SCAN_COL3 : col_data <= 4'b0111; //scan the 4th row if the key is down SCAN_READ : begin row_data_r <= row_data; //register the sudden col_data col_data_r <= col_data; //register the sudden row_data end //SCAN_JITTER2: default:; //default vaule Endcase
当col_data为某一值的时候,若row_data!=4'b1111,则可确定是该列的键被按下!从而可以通过{row_data,col_data}来确定被按下的键。
1.1.1. 状态机
采用三段式状态机描述整个矩阵键盘的扫描状态控制,状态如下:
parameter SCAN_IDLE = 3'd0; 表示初始化状态 parameter SCAN_JITTER1= 3'd1; 表示消抖动状态 parameter SCAN_COL0 = 3'd2; 表示Col0检测状态 parameter SCAN_COL1 = 3'd3; 表示Col1检测状态 parameter SCAN_COL2 = 3'd4; 表示Col2检测状态 parameter SCAN_COL3 = 3'd5; 表示Col3检测状态 parameter SCAN_READ = 3'd6; 表示读取{Row[3:0],Col[3:0]}键值 parameter SCAN_JITTER2= 3'd7; 表示按键松手检测
其中消抖动为了简便,做了20ms状态检测计,如下:
//--------------------------------------- //generate for 20ms signal localparam KEY_DELAY = 20'hf_ffff; //50MHz, 20ms reg [19:0] delay_cnt; always @(posedge clk or negedge rst_n) begin if(!rst_n) delay_cnt <= 0; else if(delay_cnt < KEY_DELAY) //(current_state == SCAN_JITTER1) delay_cnt <= delay_cnt + 1'b1; else delay_cnt <= 20'd0; end wire delay_20ms = (delay_cnt == KEY_DELAY) ? 1'b1 : 1'b0;//key is down
状态机如下:
1.1.1. 仿真图
通过testbench仿真,符合预期目标,结果如下:
时序及编码
case ({row_data_r, col_data_r}) 8'b0111_0111: key_value <= 4'h0; 8'b0111_1011: key_value <= 4'h1; 8'b0111_1101: key_value <= 4'h2; 8'b0111_1110: key_value <= 4'h3; 8'b1011_0111: key_value <= 4'h4; 8'b1011_1011: key_value <= 4'h5; 8'b1011_1101: key_value <= 4'h6; 8'b1011_1110: key_value <= 4'h7; 8'b1101_0111: key_value <= 4'h8; 8'b1101_1011: key_value <= 4'h9; 8'b1101_1101: key_value <= 4'hA; 8'b1101_1110: key_value <= 4'hB; 8'b1110_0111: key_value <= 4'hC; 8'b1110_1011: key_value <= 4'hD; 8'b1110_1101: key_value <= 4'hE; 8'b1110_1110: key_value <= 4'hF; default : key_value <= key_value; endcase
每次接受到key_flag一个触发的高电平,表示按键按下,可以直接读取键值,进行相应的操作!接口如下:
//---------------------------------------------- //the target component instantiation matrix_key_scan u_matrix_key_scan ( .clk (clk), //global clock .rst_n (rst_n), //global reset .row_data (row_data), //row data: pull-up with 3.3V .col_data (col_data), //column data: for key scan .key_flag (key_flag), //the mark of key is pressed .key_value (key_value) //the returned value of matrix key );
用户516101 2013-10-13 15:48
用户434882 2013-3-22 10:52
用户1587968 2013-3-5 21:27
345002072_353389109 2013-3-2 18:53
博主做的挺好的,加油!