1.1 GPIO概念
GPIO(general purpose intput output)是通用输入输出端口的简称,可以通过软件来控制其输入和输出。(开发板上使用的 DSP 型号是 TMS320F28335,此芯片共有 176 引脚)
(1)电源引脚
(2)晶振引脚
(3)复位引脚
(4)下载引脚
(5)BOOT引脚
(6)GPIO 引脚
1.2 GPIO结构框图
GPIO输出设置:
void LED_Init(void) { EALLOW;//关闭写保护 SysCtrlRegs.PCLKCR3.bit.GPIOINENCLK = 1; // 开启GPIO时钟 //LED1端口配置 GpioCtrlRegs.GPCMUX1.bit.GPIO68=0;//设置为通用GPIO功能 0-通用输出 1-外设1输出 2-外设2输出 3-外设3输出 GpioCtrlRegs.GPCDIR.bit.GPIO68=1;//设置GPIO方向为输出 1-输出 0-输入 GpioCtrlRegs.GPCPUD.bit.GPIO68=0;//使能GPIO上拉电阻 0-使能上拉 1-禁止上拉 GpioDataRegs.GPCSET.bit.GPIO68=1;//设置GPIO输出高电平 //GpioDataRegs.GPCCLEAR.bit.GPIO68 = 1; //设置GPIO输出为低电平 EDIS;//开启写保护 }
GPIO输入设置:
DSP GPIO作为输入时,硬件自带滤波功能,通过设置指定寄存器达到3次或6次采样滤波
1.3 GPIO相关寄存器
蜂鸣器是一种一体化结构的电子讯响器,采用直流电压供电,广泛应用于计算机、 打印机、 复印机、 报警器、 电子玩具、 汽车电子设备、 电话机、 定时器等电子产品中作发声器件。蜂鸣器主要分为压电式蜂鸣器和电磁式蜂鸣器两种类型。 压电式蜂鸣器主要由多谐振荡器、 压电蜂鸣片、 阻抗匹配器及共鸣箱、 外壳等组成。 多谐振荡器由晶体管或集成电路构成, 当接通电源后( 1.5~15V 直流工作电压),多谐振荡器起振,输出 1.5~5kHZ 的音频信号, 阻抗匹配器推动压电蜂鸣片发声。(无源蜂鸣器,因为没有振荡器,体积大,底部看不见电路板)
电磁式蜂鸣器由振荡器、 电磁线圈、 磁铁、 振动膜片及外壳等组成。接通电源后,振荡器产生的音频信号电流通过电磁线圈, 使电磁线圈产生磁场, 振动膜片在电磁线圈和磁铁的相互作用下,周期性地振动发声。(有源蜂鸣器,体积小,底部看得见电路板)
蜂鸣器驱动时需要外加驱动芯片,GPIO口驱动电流不能达到蜂鸣器工作电流,图中为无源蜂鸣器,需要输出脉冲才能工作
#define BEEP_ON (GpioDataRegs.GPASET.bit.GPIO6=1) #define BEEP_OFF (GpioDataRegs.GPACLEAR.bit.GPIO6=1) #define BEEP_TOGGLE (GpioDataRegs.GPATOGGLE.bit.GPIO6=1) //不能加分号 void BEEP1_Init(void) { EALLOW; SysCtrlRegs.PCLKCR3.bit.GPIOINENCLK = 1;// 开启GPIO时钟 //BEEP端口配置 GpioCtrlRegs.GPAMUX1.bit.GPIO6=0; GpioCtrlRegs.GPADIR.bit.GPIO6=1; GpioCtrlRegs.GPAPUD.bit.GPIO6=0; GpioDataRegs.GPACLEAR.bit.GPIO6=1; EDIS; } void main() { int i = 0; InitSysCtrl();//系统时钟初始化,默认已开启F28335所有外设时钟 LED1_Init(); BEEP1_Init(); while(1) { i++; BEEP_TOGGLE; //GPIO翻转 if(i%1000==0) { LED1_TOGGLE; } DELAY_US(100); //延时可以使GPIO端口输出脉冲 驱动蜂鸣器工作 } }
1.按键介绍
按键是一种电子开关,使用时轻轻按开关按钮就可使开关接通,当松开手时,开关断开。
1.1 矩阵键盘介绍
矩阵键盘检测方法有多种,最常用的是行列扫描和线翻转法。 行列扫描法检测时, 先送一列为低电平, 其余几列全为高电平(此时我们确定了列数),然后立即轮流检测一次各行是否有低电平, 若检测到某一行为低电平(这时我们又确定了行数), 则我们便可确认当前被按下的键是哪一行哪一列的, 用同样方法轮流送各列一次低电平,再轮流检测一次各行是否变为低电平, 这样即可检测完所有的按键, 当有键被按下时便可判断出按下的键是哪一个键。 当然我们也可以将行线置低电平, 扫描列是否有低电平。 从而达到整个键盘的检测。
线翻转法,就是使所有行线为低电平时,检测所有列线是否有低电平,如果有, 就记录列线值;然后再翻转, 使所有列线都为低电平, 检测所有行线的值, 由于有按键按下,行线的值也会有变化, 记录行线的值。 从而就可以检测到全部按键。
2.硬件设计
3.软件设计
#define KEY_L1_SetL (GpioDataRegs.GPBCLEAR.bit.GPIO48=1) #define KEY_L2_SetL (GpioDataRegs.GPBCLEAR.bit.GPIO49=1) #define KEY_L3_SetL (GpioDataRegs.GPBCLEAR.bit.GPIO50=1) #define KEY_L1_SetH (GpioDataRegs.GPBSET.bit.GPIO48=1) #define KEY_L2_SetH (GpioDataRegs.GPBSET.bit.GPIO49=1) #define KEY_L3_SetH (GpioDataRegs.GPBSET.bit.GPIO50=1) #define KEY_H1 (GpioDataRegs.GPADAT.bit.GPIO12) #define KEY_H2 (GpioDataRegs.GPADAT.bit.GPIO13) #define KEY_H3 (GpioDataRegs.GPADAT.bit.GPIO14) #define KEY1_PRESS 1 #define KEY2_PRESS 2 #define KEY3_PRESS 3 #define KEY4_PRESS 4 #define KEY5_PRESS 5 #define KEY6_PRESS 6 #define KEY7_PRESS 7 #define KEY8_PRESS 8 #define KEY9_PRESS 9 #define KEY_UNPRESS 0 void KEY_Init(void) { EALLOW; SysCtrlRegs.PCLKCR3.bit.GPIOINENCLK = 1;// 开启GPIO时钟 //KEY端口配置 /*GPIO输入端*/ GpioCtrlRegs.GPAMUX1.bit.GPIO12=0; GpioCtrlRegs.GPADIR.bit.GPIO12=0; // GPIO设置为输入 GpioCtrlRegs.GPAPUD.bit.GPIO12=0; GpioCtrlRegs.GPAMUX1.bit.GPIO13=0; GpioCtrlRegs.GPADIR.bit.GPIO13=0; // GPIO设置为输入 GpioCtrlRegs.GPAPUD.bit.GPIO13=0; GpioCtrlRegs.GPAMUX1.bit.GPIO14=0; GpioCtrlRegs.GPADIR.bit.GPIO14=0; // GPIO设置为输入 GpioCtrlRegs.GPAPUD.bit.GPIO14=0; /*GPIO输出端*/ GpioCtrlRegs.GPBMUX2.bit.GPIO48=0; GpioCtrlRegs.GPBDIR.bit.GPIO48=1; // GPIO设置为输出 GpioCtrlRegs.GPBPUD.bit.GPIO48=0; GpioCtrlRegs.GPBMUX2.bit.GPIO49=0; GpioCtrlRegs.GPBDIR.bit.GPIO49=1; // GPIO设置为输出 GpioCtrlRegs.GPBPUD.bit.GPIO49=0; GpioCtrlRegs.GPBMUX2.bit.GPIO50=0; GpioCtrlRegs.GPBDIR.bit.GPIO50=1; // GPIO设置为输出 GpioCtrlRegs.GPBPUD.bit.GPIO50=0; GpioDataRegs.GPBSET.bit.GPIO48=1; GpioDataRegs.GPBSET.bit.GPIO49=1; GpioDataRegs.GPBSET.bit.GPIO50=1; EDIS; } char KEY_Scan(char mode) //mode=0 单次扫描 mode=1 循环扫描 { static char keyl1=1; static char keyl2=1; static char keyl3=1; //第1列扫描 KEY_L1_SetL; KEY_L2_SetH; KEY_L3_SetH; if(keyl1==1&&(KEY_H1==0||KEY_H2==0||KEY_H3==0)) { DELAY_US(10000); //消抖 keyl1=0; if(KEY_H1==0) { return KEY1_PRESS; } else if(KEY_H2==0) { return KEY4_PRESS; } else if(KEY_H3==0) { return KEY7_PRESS; } } else if(KEY_H1==1&&KEY_H2==1&&KEY_H3==1) { keyl1=1; } if(mode) keyl1=1; //第2列扫描 KEY_L2_SetL; KEY_L1_SetH; KEY_L3_SetH; if(keyl2==1&&(KEY_H1==0||KEY_H2==0||KEY_H3==0)) { DELAY_US(10000);//消抖 keyl2=0; if(KEY_H1==0) { return KEY2_PRESS; } else if(KEY_H2==0) { return KEY5_PRESS; } else if(KEY_H3==0) { return KEY8_PRESS; } } else if(KEY_H1==1&&KEY_H2==1&&KEY_H3==1) { keyl2=1; } if(mode) keyl2=1; //第3列扫描 KEY_L3_SetL; KEY_L1_SetH; KEY_L2_SetH; if(keyl3==1&&(KEY_H1==0||KEY_H2==0||KEY_H3==0)) { DELAY_US(10000);//消抖 keyl3=0; if(KEY_H1==0) { return KEY3_PRESS; } else if(KEY_H2==0) { return KEY6_PRESS; } else if(KEY_H3==0) { return KEY9_PRESS; } } else if(KEY_H1==1&&KEY_H2==1&&KEY_H3==1) { keyl3=1; } if(mode) keyl3=1; return KEY_UNPRESS; } void main() { int i=0; char key=0; InitSysCtrl(); LED_Init(); KEY_Init(); while(1) { key=KEY_Scan(0); switch(key) { case KEY1_PRESS: LED2_TOGGLE;break; case KEY2_PRESS: LED3_TOGGLE;break; case KEY3_PRESS: LED4_TOGGLE;break; case KEY4_PRESS: LED5_TOGGLE;break; case KEY5_PRESS: LED6_TOGGLE;break; case KEY6_PRESS: LED7_TOGGLE;break; } i++; if(i%2000==0) { LED1_TOGGLE; } DELAY_US(100); } }