1. 程式人生 > >STM32與CH455g通訊測試(僅鍵盤)

STM32與CH455g通訊測試(僅鍵盤)

1、概述

  CH455是數碼管顯示驅動和鍵盤掃描控制晶片。CH455內建時鐘振盪電路,可以動態驅動4位數碼管或者32只LED;同時還可以進行28鍵的鍵盤掃描;CH455通過SCL和SDA組成的2線序列介面與微控制器等交換資料。

2、特點

●內建顯示電流驅動級,段電流不小於25mA,字電流不小於160mA。

●動態顯示掃描控制,支援8×4或者7×4,直接驅動4位數碼管或者32只發光管LED。

●內部限流,通過佔空比設定提供8級亮度控制。

●內建28鍵鍵盤控制器,基於7×4矩陣鍵盤掃描。

●內建按鍵狀態輸入的下拉電阻,內建去抖動電路。

●提供低電平有效的鍵盤中斷,提供按鍵釋放標誌位,可供查詢按鍵按下與釋放。

●高速2線序列介面,時鐘速度從0到4MHz,相容兩線I2C匯流排,節約引腳。

●內建上電覆位,支援2.7V~5V電源電壓。

●支援低功耗睡眠,節約電能,可以被按鍵喚醒或者被命令操作喚醒。

●內建時鐘振盪電路,不需要外部提供時鐘或者外接振盪元器件,更抗干擾。

3、引腳介紹

VCC:電源正電源,持續電流不小於150mA

GND:電源公共接地,持續電流不小於150mA

SEG0 ~SEG6:三態輸出及輸入數碼管的段驅動,高電平有效,鍵盤掃描輸入,高電平有效,內建下拉

SEG7:輸出數碼管的小數點段驅動輸出,高電平有效,7段模式下的鍵盤中斷輸出,低電平有效

DIG0 ~DIG3:輸出數碼管的字驅動,低電平有效,鍵盤掃描輸出,高電平有效

SDA:內建上拉開漏輸出及輸入2線序列介面的資料輸入和輸出,內建上拉電阻SCL:輸入2線序列介面的資料時鐘,內建上拉電阻

4、鍵盤掃描功能

  鍵盤掃描CH455的鍵盤掃描功能支援7×4矩陣的28鍵鍵盤。在鍵盤掃描期間,DIG3~DIG0引腳用於列掃描輸出,SEG6~SEG0引腳都帶有內部下拉電阻,用於行掃描輸入。CH455定期在顯示驅動掃描過程中插入鍵盤掃描。在鍵盤掃描期間,DIG3~DIG0引腳按照DIG0至DIG3的順序依次輸出高電平,其餘引腳輸出低電平;SEG6~SEG0引腳的輸出被禁止,當沒有鍵被按下時,SEG6~SEG0都被下拉為低電平;當有鍵被按下時,例如連線DIG1與SEG4的鍵被按下,則當DIG1輸出高電平時SEG4檢測到高電平;為了防止因為按鍵抖動或者外界干擾而產生誤碼,CH455實行兩次掃描,只有當兩次鍵盤掃描的結果相同時,按鍵才會被確認有效。如果CH455檢測到有效的按鍵,則記錄下該按鍵程式碼,並通過INT#引腳產生低電平有效的鍵盤中斷,此時微控制器可以通過序列介面讀取按鍵程式碼;在沒有檢測到新的有效按鍵之前,CH455不再產生任何鍵盤中斷。CH455支援SEG1和SEG0針對同一DIG的組合鍵,組合鍵是最優先的,除此之外,如果多個鍵同時按下,那麼按鍵程式碼較小的按鍵優先。例如連線DIG1與SEG1及連線DIG1與SEG0的兩個鍵,可作為組合鍵。CH455所提供的按鍵程式碼為8位,位7始終為0,位2始終為1,位1~位0是列掃描碼,位5~位3是行掃描碼,位6是狀態碼(鍵按下為1,鍵釋放為0)。例如,連線DIG1與SEG4的鍵被按下,則按鍵程式碼是01100101B或者65H,鍵被釋放後,按鍵程式碼通常是00100101B或者25H(也可能是其它值,但是肯定小於40H),其中,對應DIG1的列掃描碼為01B,對應SEG4的行掃描碼為100B。微控制器可以在任何時候讀取按鍵程式碼,但一般在CH455檢測到有效按鍵而產生鍵盤中斷時讀取按鍵程式碼,此時按鍵程式碼的位6總是1,另外,如果需要了解按鍵何時釋放,微控制器可以通過查詢方式定期讀取按鍵程式碼,直到按鍵程式碼的位6為0。下表是在DIG3~DIG0與SEG6~SEG0之間7×4矩陣的按鍵編址,也是數碼管段位和發光管LED陣列的順序編址。由於按鍵程式碼是8位,鍵按下時位6總是1,所以當鍵按下時,CH455所提供的實際按鍵程式碼是表中的按鍵編址加上40H,也就是說,此時的按鍵程式碼應該在44H到7FH之間。

編址 DIG3 DIG2 DIG1 DIG0
SEG0 07H 06H 05H 04H
SEG1 0FH 0EH 0DH 0CH
SEG2 17H 16H 15H 14H
SEG3 1FH 1EH 1DH 1CH
SEG4 27H 26H 25H 24H
SEG5 2FH 2EH 2DH 2CH
SEG6 37H 36H 35H 34H
SEG0+SEG1 3FH 3EH 3DH 3CH

 

 

 

 

 

 

 

 

 

 

 

5、序列介面

  CH455具有硬體實現的2線序列介面,包含2個主要訊號線:序列資料時鐘輸入線SCL、序列資料輸入和輸出線SDA;以及1個輔助訊號線:中斷輸出線INT#。其中,SCL是帶上拉的輸入訊號線,CH455中文手冊4預設是高電平;SDA是帶上拉的準雙向訊號線,預設是高電平;INT#是帶上拉的開漏輸出,在啟用鍵盤掃描功能後作為鍵盤中斷輸出線,預設是高電平。SDA用於序列資料輸入和輸出,高電平表示位資料1,低電平表示位資料0,序列資料輸入的順序是高位在前,低位在後。SCL用於提供序列時鐘,CH455在其上升沿從SDA輸入資料,在其下降沿從SDA輸出資料。在SCL為高電平期間發生的SDA下降沿定義為序列介面的啟動訊號,在SCL為高電平期間發生的SDA上升沿定義為序列介面的停止訊號。CH455只在檢測到啟動訊號後才接收並分析命令。所以在微控制器I/O引腳資源緊張時,可以在保持SDA引腳狀態不變的情況下,將SCL引腳與其它介面電路共用;如果能夠確保SDA引腳的變化僅在SCL引腳為低電平期間發生,那麼SCL引腳和SDA引腳都可以與其它介面電路共用。INT#用於鍵盤中斷輸出,預設是高電平。當CH455檢測到有效按鍵時,INT#輸出低電平有效的鍵盤中斷;微控制器被中斷後,對CH455執行讀操作,CH455將INT#恢復為高電平,並從SDA輸出按鍵程式碼,微控制器從SDA獲得一個位元組的資料,即按鍵程式碼。微控制器與CH455的通訊過程總是分為6個步驟,按微控制器的操作方向分成兩種型別,一種是寫操作,用於輸出資料,一種是讀操作,用於輸入資料。具體過程可以參考例子程式中的說明。寫操作包括以下6個步驟:輸出啟動訊號、輸出位元組1、應答1、輸出位元組2、應答2、輸出停止訊號。其中,啟動訊號和停止訊號如上所述,應答1和應答2總是固定為1,輸出位元組1和輸出位元組2各自包含8個數據位,即一個位元組資料。讀操作包括以下6個步驟:輸出啟動訊號、輸出位元組1、應答1、輸入位元組2、應答2、輸出停止訊號。其中,啟動訊號和停止訊號如上所述,應答1和應答2總是固定為1,輸出位元組1和輸入位元組2各自包含8個數據位,即一個位元組資料。

6、操作命令

  CH455的操作命令分為3組。各命令的啟動訊號、停止訊號、應答1和應答2都相同,區別在於輸出位元組1和位元組2的資料不同以及位元組2的傳輸方向不同。

載入字資料命令:該命令的輸出位元組1為地址68H、6AH、6CH或者6EH,分別對應於DIG0~DIG3引腳驅動的4個數碼管;輸出位元組2為[DIG_DATA]B,即00H到0FFH之間的值,是8位的字資料。載入字資料命令用於將字資料DIG_DATA寫入位元組1指定地址的資料暫存器中。例如,命令資料01101100B(即6CH對應DIG2)、01111001B表示將字資料79H寫入第1個數據暫存器,使DIG2引腳驅動的數碼管將顯示E。

讀取按鍵程式碼命令:該命令的輸出位元組1為01001111B,即4FH;輸入位元組2為按鍵程式碼。讀取按鍵程式碼命令用於獲得CH455最近檢測到的有效按鍵的按鍵程式碼。該命令屬於讀操作,是唯一的具有資料返回的命令,微控制器必須先釋放SDA引腳(三態輸出禁止或者上拉到高電平),然後CH455從SDA引腳輸出按鍵程式碼,按鍵程式碼的有效資料是位7~位0,其中位6是狀態碼,位5~位0是掃描碼和按鍵編址。

7、介面時序

  

TSSTA/THSTA/TSSTO/THSTO/TCLOW/TCHIG:最小時間100ns

TSD:最小時間30ns

THD:最小時間10ns

TAA/TDH:最小時間2ns

Rate:最大速率4Mbps

8、原理圖接線

9、程式設計

   由於這次只是做個簡單的按鍵檢測,所以只用到鍵盤掃描功能,數碼管有需要再做吧。先定義一下系統引數:

// 設定系統引數命令
#define CH455_SCL_SET         HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET)
#define CH455_SCL_CLR         HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET)
#define CH455_SCL_D_OUT        {}  // 設定SCL為輸出方向,對於雙向I/O需切換為輸出

#define CH455_SDA_SET         HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET)
#define CH455_SDA_CLR         HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET)
#define CH455_SDA_IN           HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_9)     //  讀取SDA輸入電平

#define CH455_BIT_ENABLE    0x01        // 開啟/關閉位
#define CH455_BIT_SLEEP        0x04        // 睡眠控制位
#define CH455_BIT_7SEG        0x08        // 7段控制位
#define CH455_BIT_INTENS1    0x10        // 1級亮度
#define CH455_BIT_INTENS2    0x20        // 2級亮度
#define CH455_BIT_INTENS3    0x30        // 3級亮度
#define CH455_BIT_INTENS4    0x40        // 4級亮度
#define CH455_BIT_INTENS5    0x50        // 5級亮度
#define CH455_BIT_INTENS6    0x60        // 6級亮度
#define CH455_BIT_INTENS7    0x70        // 7級亮度
#define CH455_BIT_INTENS8    0x00        // 8級亮度

#define CH455_SYSOFF    0x0400            // 關閉顯示、關閉鍵盤
#define CH455_SYSON        ( CH455_SYSOFF | CH455_BIT_ENABLE )    // 開啟顯示、鍵盤
#define CH455_SLEEPOFF    CH455_SYSOFF    // 關閉睡眠
#define CH455_SLEEPON    ( CH455_SYSOFF | CH455_BIT_SLEEP )    // 開啟睡眠
#define CH455_7SEG_ON    ( CH455_SYSON | CH455_BIT_7SEG )    // 開啟七段模式
#define CH455_8SEG_ON    ( CH455_SYSON | 0x00 )    // 開啟八段模式
#define CH455_SYSON_4    ( CH455_SYSON | CH455_BIT_INTENS4 )    // 開啟顯示、鍵盤、4級亮度
#define CH455_SYSON_8    ( CH455_SYSON | CH455_BIT_INTENS8 )    // 開啟顯示、鍵盤、8級亮度

// CH455介面定義
#define        CH455_I2C_ADDR        0x40            // CH455的地址
#define        CH455_I2C_MASK        0x3E            // CH455的高位元組命令掩碼

// 讀取按鍵程式碼命令
#define CH455_GET_KEY    0x0700                    // 獲取按鍵,返回按鍵程式碼
define

另外,用的是stm32的HAL庫,但是IIC通訊依然用的是IO口模擬IIC的,主要是因為CH455g的器件地址沒有找到,其次是HAL庫自帶的IIC模組不太可靠。

//--------------------------------------------i2c-------------------------------------------
// 設定SDA為輸出方向,對於雙向I/O需切換為輸出
void CH455_SDA_D_OUT()
{  
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    GPIO_InitStruct.Pin = GPIO_PIN_9;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    
}

// 設定SDA為輸入方向,對於雙向I/O需切換為輸入
void CH455_SDA_D_IN()
{  
    GPIO_InitTypeDef GPIO_InitStruct = {0};
  GPIO_InitStruct.Pin = GPIO_PIN_9;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    
}

void CH455_I2c_Start( void )  // 操作起始
{
    //DISABLE_KEY_INTERRUPT;  //禁止鍵盤中斷,防止開始時被CH455中斷而進入中斷服務程式中的START
    
    CH455_SDA_SET;   /*傳送起始條件的資料訊號*/
    CH455_SDA_D_OUT();   /* 設定SDA為輸出方向 */
    CH455_SCL_SET;
    CH455_SCL_D_OUT;   /* 設定SCL為輸出方向 */
    HAL_Delay(10);
    CH455_SDA_CLR;   /*傳送起始訊號*/
    HAL_Delay(10);      
    CH455_SCL_CLR;   /*鉗住I2C匯流排,準備傳送或接收資料 */
}

void CH455_I2c_Stop( void )  // 操作結束
{
    CH455_SDA_CLR;
    CH455_SDA_D_OUT();   /* 設定SDA為輸出方向 */
    HAL_Delay(10);
    CH455_SCL_SET;
    HAL_Delay(10);
    CH455_SDA_SET;  /*傳送I2C匯流排結束訊號*/
    HAL_Delay(10);
    CH455_SDA_D_IN();   /* 設定SDA為輸入方向 */
    //ENABLE_KEY_INTERRUPT;
}

void CH455_I2c_WrByte( uint8_t dat )    //寫一個位元組資料
{
    uint8_t i;
    CH455_SDA_D_OUT();   /* 設定SDA為輸出方向 */
    for( i = 0; i != 8; i++ )  // 輸出8位資料
    {
        if( dat & 0x80 ) 
        {
            CH455_SDA_SET;
        }
        else 
        {
            CH455_SDA_CLR;
        }
        HAL_Delay(10);
        CH455_SCL_SET;
        dat <<= 1;
        HAL_Delay(10);  // 可選延時
        CH455_SCL_CLR;
    }
    CH455_SDA_D_IN();   /* 設定SDA為輸入方向 */
    CH455_SDA_SET;
    HAL_Delay(10);
    CH455_SCL_SET;  // 接收應答
    HAL_Delay(10);
    CH455_SCL_CLR;
}

uint8_t  CH455_I2c_RdByte( void )        //讀一個位元組資料
{
    uint8_t dat,i;
    CH455_SDA_SET;
    CH455_SDA_D_IN();   /* 設定SDA為輸入方向 */
    dat = 0;
    for( i = 0; i != 8; i++ )  // 輸入8位資料
    {
        HAL_Delay(10);  // 可選延時
        CH455_SCL_SET;
        HAL_Delay(10);  // 可選延時
        dat <<= 1;
        if( CH455_SDA_IN ) dat++;  // 輸入1位
        CH455_SCL_CLR;
    }
    CH455_SDA_SET;
    HAL_Delay(10);
    CH455_SCL_SET;  // 發出無效應答
    HAL_Delay(10);
    CH455_SCL_CLR;
    return dat;
}

void CH455_Write( uint16_t cmd )    //寫命令
{
    CH455_I2c_Start();               //啟動匯流排
  CH455_I2c_WrByte(((uint8_t)(cmd>>7)&CH455_I2C_MASK)|CH455_I2C_ADDR);
  CH455_I2c_WrByte((uint8_t)cmd);               //傳送資料
  CH455_I2c_Stop();                 //結束匯流排 
}

uint8_t CH455_Read( void )        //讀取按鍵
{
    uint8_t keycode;
       CH455_I2c_Start();                //啟動匯流排
       CH455_I2c_WrByte((uint8_t)(CH455_GET_KEY>>7)&CH455_I2C_MASK|0x01|CH455_I2C_ADDR);
       keycode=CH455_I2c_RdByte();      //讀取資料
    CH455_I2c_Stop();                //結束匯流排
    return keycode;
}
IO口模擬IIC

 主函式開啟中斷和鍵盤:

HAL_ADC_Start_IT(&hadc1);
CH455_Write( CH455_7SEG_ON );// 開啟顯示和鍵盤,8段顯示方式

 寫完回撥函式,即可列印輸出鍵碼:

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* AdcHandle)
{
    RX_AD = HAL_ADC_GetValue(&hadc1);
    if(RX_AD == 0)
    {
        RX_CH455 = CH455_Read();
        printf("鍵碼:%x\r\n",RX_CH455);
    }
}

完了給大夥看看按鍵列印結果:

需要程式的記得留言打