天天看點

DSP28335的3X3矩陣鍵盤掃描,用LCD1602顯示

LCD1602隻能顯示字元,,需要把按鍵值對應的數字量轉成字元量來顯示,否則顯示錯誤

/***************************************************
使用GPIO0-GPIO11,液晶與其對應的引腳如下所示:
//
//        RS--GPIO0引腳,
    	  R/W--GND,
    	  EN--GPIO1引腳,
    	  D0--GPIO2引腳
//        D1--GPIO3引腳,
 * 		  D2--GPIO4引腳,
 *        D3--GPIO5引腳,
 *        D4--GPIO6引腳
//        D5--GPIO7引腳,
 *        D6--GPIO8引腳,
 *        D7--GPIO9引腳;
 *
 *按鍵掃描,,三行接的是GPIO12  13  14
                        三列接的是GPIO48  49  50
                        按鍵掃描原理: 1、3列對應的IO設定為輸出,3行對應的IO設定為輸入。其實
					   2、若無按鍵按下,3行輸入IO,均為高電平(因為有外部上拉電阻)
					   3、若按鍵按下,對應行IO被拉低(假設為第X行),檢測為低電平。按鍵所在行(X行),被鑒别出來。
					   4、此時,依次改變3列的輸出為高,當遇到按鍵所在列時,第X行電平重新變為高。按鍵所在列。被鑒别出來。
			觀測變量Key的值來判斷哪個按鍵按下了;
 *       ****************************************************/
#include "DSP2833x_Device.h"
#include "DSP2833x_Examples.h"
/***************************************************
                                               宏定義
*************************************************/
//1602部分宏定義
#define uchar unsigned char
#define LCD_RS GpioDataRegs.GPADAT.bit.GPIO0
#define LCD_EN GpioDataRegs.GPADAT.bit.GPIO1
#define LCD_DB GpioDataRegs.GPADAT.all

//key部分宏定義
#define		SET_KY1		GpioDataRegs.GPBSET.bit.GPIO48 = 1
#define		SET_KY2		GpioDataRegs.GPBSET.bit.GPIO49 = 1
#define		SET_KY3		GpioDataRegs.GPBSET.bit.GPIO50 = 1
#define		RST_KY1		GpioDataRegs.GPBCLEAR.bit.GPIO48 = 1
#define		RST_KY2		GpioDataRegs.GPBCLEAR.bit.GPIO49 = 1
#define		RST_KY3		GpioDataRegs.GPBCLEAR.bit.GPIO50 = 1
#define		KX1_STATUS  GpioDataRegs.GPADAT.bit.GPIO12
#define		KX2_STATUS  GpioDataRegs.GPADAT.bit.GPIO13
#define		KX3_STATUS  GpioDataRegs.GPADAT.bit.GPIO14

/**************************************************
                                            函數聲明
*****************************************************/
//1602部分函數
void Init_Port(void);//初始化1602使用的GPIO端口
void LCD_init(void);//初始化Lcd1602
void LCD_write_command(uchar command);//LCDD寫指令函數
void LCD_write_data(uchar dat);//LCD寫資料函數
void show(char *cont);//LCD顯示函數
//key部分函數
void Init_KeyGpio(void);//初始化3X3矩陣鍵盤對應的GPIO端口
void delay(Uint32 t);//軟體延時函數
void ResetAllKY(void);//用于複位所有列端口的函數
void KX_AllStatus(void);//用于讀取所有行端口的電平狀态的函數
void Read_KX(Uint16 x);//讀取按鍵行值的函數
void Read_KY(Uint16 x);//讀取按鍵列值的函數
void Set_KY(Uint16 x);//用于将某一列對應端口置高的函數
void Rst_KY(Uint16 x);//用于将某一列對應端口置低的函數

/*********************************************************
                                                   變量設定
 *******************************************************/
Uint16 Keys[3][3] = {1,2,3,4,5,6,7,8,9};
Uint16 Key = 0;
uchar  p;
Uint16 KX_On = 0;
Uint16 KX_Tim[5] = {0};
Uint16 KX_Status[5]={0};
Uint16 KY_On = 0;


void main(void)
{
	InitSysCtrl();

	Init_Port();
	Init_KeyGpio();

	DINT;
	InitPieCtrl();
	IER = 0x00000000;
	IFR = 0x00000000;
	InitPieVectTable();

	for(;;)
	{
		LCD_init();
		LCD_write_command(0x80);
		show("Key number: ");


		while(1)
		{
			Read_KX(1);
			Read_KX(2);
			Read_KX(3);

			Read_KY(1);
			Read_KY(2);
			Read_KY(3);



		}

	}
}

//LCD1602部分函數
void Init_Port(void)
{
	EALLOW;

	GpioCtrlRegs.GPAMUX1.all = 0x00000000;
	GpioCtrlRegs.GPADIR.all = 0x00000FFF;

	GpioDataRegs.GPADAT.bit.GPIO0 = 0;
	GpioDataRegs.GPADAT.bit.GPIO1 = 0;
	
	EDIS;
}

//LCD初始化函數,,嚴格按照初始化順序來進行,延時,寫指令
void LCD_init(void)
{
	DELAY_US(15000);
	LCD_write_command(0x38);
	DELAY_US(5000);
	LCD_write_command(0x38);
	DELAY_US(5000);
	LCD_write_command(0x38);
	LCD_write_command(0x38);
	LCD_write_command(0x08);
	LCD_write_command(0x01);
	LCD_write_command(0x06);
	LCD_write_command(0x0c);
}
void LCD_write_command(uchar command)
{
	LCD_EN = 0;
	LCD_RS = 0;
	LCD_DB = (command << 2) | 0x0000;//這個地方0x0000,,為了保證在或運算時候,LCD_EN=0,LCD_RS=0保持不變
	DELAY_US(500);
	LCD_EN = 1;
	DELAY_US(1000);
	LCD_EN = 0;//最後三行制造了一個1ms的高脈沖
}
void show(char *cont)
{
	while(*cont != 0)
	{
		LCD_write_data(*cont);
		DELAY_US(500);
		cont++;
	}
}
void LCD_write_data(uchar dat)
{
	LCD_EN = 0;
	LCD_RS = 1;
	LCD_DB = (dat << 2) | 0x0001;//這個地方。0x0001,,為了保證在或運算過程中,LCD_EN=0,LCD_RS=1保持不變,注意與上面LCD_write_command函數中的差別
	DELAY_US(500);
	LCD_EN = 1;
	DELAY_US(1000);
	LCD_EN = 0;//最後三行制造了一個1ms的高脈沖
}
//Key部分函數
void Init_KeyGpio(void)
{
	EALLOW;
	//GPIO48初始化,輸出,低電平
	GpioCtrlRegs.GPBMUX2.bit.GPIO48 = 0;
	GpioCtrlRegs.GPBDIR.bit.GPIO48 = 1;
	GpioDataRegs.GPBCLEAR.bit.GPIO48 = 1;
	GpioCtrlRegs.GPBPUD.bit.GPIO48 = 0;
	//GPIO49初始化,輸出,低電平
	GpioCtrlRegs.GPBMUX2.bit.GPIO49 = 0;
	GpioCtrlRegs.GPBDIR.bit.GPIO49 = 1;
	GpioDataRegs.GPBCLEAR.bit.GPIO49 = 1;
	GpioCtrlRegs.GPBPUD.bit.GPIO49 = 0;
	//GPIO50初始化,輸出,低電平
	GpioCtrlRegs.GPBMUX2.bit.GPIO50 = 0;
	GpioCtrlRegs.GPBDIR.bit.GPIO50 = 1;
	GpioDataRegs.GPBCLEAR.bit.GPIO50 = 1;
	GpioCtrlRegs.GPBPUD.bit.GPIO50 = 0;

	//GPIO12 初始化   輸入
	GpioCtrlRegs.GPAMUX1.bit.GPIO12 = 0;
	GpioCtrlRegs.GPADIR.bit.GPIO12 = 0;
	GpioCtrlRegs.GPAPUD.bit.GPIO12 = 0;
	//GPIO13初始化  輸入
	GpioCtrlRegs.GPAMUX1.bit.GPIO13 = 0;
	GpioCtrlRegs.GPADIR.bit.GPIO13 = 0;
	GpioCtrlRegs.GPAPUD.bit.GPIO13 = 0;
	//GPIO14初始化  輸入
	GpioCtrlRegs.GPAMUX1.bit.GPIO14 = 0;
	GpioCtrlRegs.GPADIR.bit.GPIO14 = 0;
	GpioCtrlRegs.GPAPUD.bit.GPIO14 = 0;

	EDIS;

	ResetAllKY();
}
void ResetAllKY(void)
{
	RST_KY1;
	RST_KY2;
	RST_KY3;
}
void Read_KX(Uint16 x)
{
	KX_AllStatus();
	if(KX_Status[x] == 0)
	{
		KX_Tim[x]++;
		if(KX_Tim[x] >= 6000)//個人了解,,這個判斷類似延時消抖,,,但是這個地方換成DELAY_US函數,延時消抖,,并不太好使,,會出現按鍵值錯誤的情況
		{
			KX_On = x;
			KX_Tim[1] = 0;
			KX_Tim[2] = 0;
			KX_Tim[3] = 0;
		}
	}
}
void KX_AllStatus(void)
{
	KX_Status[1] = KX1_STATUS;
	KX_Status[2] = KX2_STATUS;
	KX_Status[3] = KX3_STATUS;
}
void Read_KY(Uint16 x)
{
	if((!KX_Status[KX_On]) && (KX_On))
	{
		Set_KY(x);
		DELAY_US(200);
		KX_AllStatus();
		if(KX_Status[KX_On])
		{
			KY_On = x;
			Key = Keys[KX_On - 1][KY_On - 1];
			p = Key + 0x30;//LCD1602隻能顯示字元,,Key+0x30是把按鍵值的數字值轉成字元值
			LCD_write_command(0x8d);
			LCD_write_data(p);
			DELAY_US(500);
			KX_On = 0;
			KY_On = 0;
		}
		Rst_KY(x);
	}
}
void Set_KY(Uint16 x)
{
	if(x == 1){SET_KY1;}
	if(x == 2){SET_KY2;}
	if(x == 3){SET_KY3;}
}
void Rst_KY(Uint16 x)
{
	if(x == 1){RST_KY1;}
	if(x == 2){RST_KY2;}
	if(x == 3){RST_KY3;}
}