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); } }
完了給大夥看看按鍵列印結果:
需要程式的記得留言打