第3题:菜单功能,按键+显示
1.在第2题的基础上,增加按键切换显示的功能,每次按键变换一次显示
2.可以通过输入数字,显示特定的内容;
************************************************************************************************
1.硬件说明
2.硬件连接
3.功能描述
4. CCS10.1.1使用小知识
5.程序代码
6. 工程文件及OLED资料
***********************************************************************************************************************
1.硬件说明
开发板:MSP432P401R LAUNCHPAD
开发环境:CCS10.1.1
矩阵按键:
SSD1306 OLED显示屏:
显示屏资料与工程文件一起在附件中。
2.硬件连接
* MSP432P401R
* ------------------
* /|\| |
* | | |
* --|RST |
* | |
* OLED | | 矩阵按键
* | P2.7 |<-- C4
* CS <--- |P1.5 P2.6 |<-- C3
* DC <--- |P6.0 P2.5 |<-- C2
* RES<--- |P6.1 P2.4 |<-- C1
* SDA<--- |P3.2 P6.6 |<-- R1 //按键R1接P5.0,灵敏度太低
* SCK<--- |P4.0 P5.1 |<-- R2
* VDD<--- |5V或3.3v P5.2 |<-- R3
* GND<--- |GND P5.6 |<-- R4
3.功能描述
* 初始状态,OLED黑屏,
* 按下按键S1,OLED上显示“ 2021 ”,
* 按下按键S2,OLED上显示“ 8.4 ”,
* 按下按键S3,OLED上显示“ NUEDC Contest ”,
* 按下按键S4,OLED上显示“ 全国大学生电子设计竞赛培训网 ”,
* 按下按键S5,OLED上显示“ 全国大学生电子设计竞赛徽章 ”,
* 按下按键S6,OLED上显示“ TI公司标志 ”,
* 按下按键S7,OLED上显示“ 欢迎大家报名参加电赛! ”,
* 按下按键S8,OLED上显示“ https://www.nuedc-training.com.cn/ ”,
* 按下按键S9,OLED上显示“ 4月份网站活动 (2) 分享代码赢板卡 ”,
* 按下按键S10,OLED上显示“ 收藏图标 ”,
* 按下按键S11,OLED上显示“ 打赏图标 ”,
* 按下按键S12,OLED上显示“ 投票图标 ”,
* 按下按键S13,OLED上显示“ 重庆大学校徽 ”,
* 按下按键S14,OLED上显示“ 重庆大学 ”,
* 按下按键S15,OLED上显示下一项内容,共14项内容可显示,显示第14项内容后再按则循环显示第14项内容,
* 按下按键S16,OLED上显示上一项内容,共14项内容可显示,显示第1项内容后再按则清屏无显示。
4. CCS10.1.1使用小知识
开发环境:CCS10.1.1
导入工程:
将例程复制到全英文路径--打开CCS--File--Open Projects from File System...--
Import source Directory...--找到要打开的工程--选择文件夹--Finish
CCS中同时修改文件中重复的语句:
选中要修改的语句--鼠标点击右键--Search Text--File--选中要修改的所有语句
--鼠标右键--Replace All...--在With一栏中输入要修改为的内容--OK
5.程序代码
*矩阵按键原理:
*4列输出接低电平,4行接上拉电阻作为中断输入,
*按键未按下时,行信号输入为高;按键按下时,行信号输入为低。
*首先所有列输出低电平,4行接上拉电阻作为中断输入,某个按键按下,则会触发按键所在行的中断。
*在中断中,第1列输出低电平,其他列输出高电平,读取输入信号,
*若输入为高,则按键不在第1列;若输入为低,则按键在第一列,再加上是哪一行的中断输入,
*就可判断是‘1’ ‘5’ ‘9’ ‘13’哪个按键按下。
*第2列再输出低电平,判断是‘2’ ‘6’ ‘10’ ‘14’哪个按键按下。
*第3列再输出低电平,判断是‘3’ ‘7’ ‘11’ ‘15’哪个按键按下。
*第4列再输出低电平,判断是‘4’ ‘8’ ‘12’ ‘16’哪个按键按下。
*程序框架说明:
*本工程采用4x4矩阵按键作为输入,SSD1306 OLED显示屏作为输出,利用 主程序死循环 + 中断输入 + OLED例程 编程。
*main.c
*主程序配置列为输出扫描信号,行为中断输入信号。
*主程序循环选择OLED显示内容,通过参数清屏,通过MoudleKey参数选择不同的显示内容。
*中断服务函数中列扫描+读行输入判断哪个按键按下,并改变MoudleKey的值。
*进入中断服务函数OledInterrupt置1,返回死循环OledInterrupt置0并清屏,根据MoudleKey的值选择对应显示内容。
*oled.c
*定义OLED有关的各种函数
*oled.h
*OLED用到的头文件和函数进行声明
*oledfont.h
*OLED的字符库和汉字库,汉字库需自己取模
*bmp.h
*OLED的图片库,图片库需自己取模
只展示main.c内容
- #include <ti/devices/msp432p4xx/driverlib/driverlib.h>
- #include <stdint.h>
- #include <stdbool.h>
- #include"oled.h"
- #include"bmp.h"
- #define ButOutHighC1 {MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P2, GPIO_PIN4);} //第1列C1输出高电平
- #define ButOutLowC1 {MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN4);} //第1列C1输出低电平
- #define ButOutHighC2 {MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P2, GPIO_PIN5);} //第2列C2输出高电平
- #define ButOutLowC2 {MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN5);} //第2列C2输出低电平
- #define ButOutHighC3 {MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P2, GPIO_PIN6);} //第3列C3输出高电平
- #define ButOutLowC3 {MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN6);} //第3列C3输出低电平
- #define ButOutHighC4 {MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P2, GPIO_PIN7);} //第4列C4输出高电平
- #define ButOutLowC4 {MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN7);} //第4列C4输出低电平
- uint32_t MoudleKey=0; //模式选择参数,第几个按键按下对应第几个OLED模式
- /*中断输入标志参数OledInterrupt。有按键按下则OLED需清屏重新显示,进入中断服务函数,OledInterrupt被置1;
- * 返回循环,OLED清屏,OledInterrupt被清0。避免OLED显示内容覆盖。*/
- int OledInterrupt =0;
- int main(void)
- {
- init(); //OLED端口定义
- OLED_Init(); //初始化SSD1306 OLED
- //配置列信号作为输出
- MAP_GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN4); //第1列C1
- MAP_GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN5); //第2列C2
- MAP_GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN6); //第3列C3
- MAP_GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN7); //第4列C4
- //所有列输出低电平
- ButOutLowC1;
- ButOutLowC2;
- ButOutLowC3;
- ButOutLowC4;
- //配置第1行R1--P6.6为上拉电阻输入并使能中断,按键R1接P5.0,灵敏度太低
- MAP_GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P6, GPIO_PIN6);
- MAP_GPIO_clearInterruptFlag(GPIO_PORT_P6, GPIO_PIN6);
- MAP_GPIO_enableInterrupt(GPIO_PORT_P6, GPIO_PIN6);
- MAP_Interrupt_enableInterrupt(INT_PORT6);
- //配置第2行R2--P5.1为上拉电阻输入并使能中断
- MAP_GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P5, GPIO_PIN1);
- MAP_GPIO_clearInterruptFlag(GPIO_PORT_P5, GPIO_PIN1);
- MAP_GPIO_enableInterrupt(GPIO_PORT_P5, GPIO_PIN1);
- //配置第3行R3--P5.2为上拉电阻输入并使能中断
- MAP_GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P5, GPIO_PIN2);
- MAP_GPIO_clearInterruptFlag(GPIO_PORT_P5, GPIO_PIN2);
- MAP_GPIO_enableInterrupt(GPIO_PORT_P5, GPIO_PIN2);
- //配置第4行R4--P5.6为上拉电阻输入并使能中断
- MAP_GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P5, GPIO_PIN6);
- MAP_GPIO_clearInterruptFlag(GPIO_PORT_P5, GPIO_PIN6);
- MAP_GPIO_enableInterrupt(GPIO_PORT_P5, GPIO_PIN6);
- MAP_Interrupt_enableInterrupt(INT_PORT5);
- //Enabling SRAM Bank Retention
- MAP_SysCtl_enableSRAMBankRetention(SYSCTL_SRAM_BANK1);
- //使能全局中断
- MAP_Interrupt_enableMaster();
- // MAP_WDT_A_holdTimer(); //关闭看门狗
- //进入模式选择循环
- while (1)
- {
- if( OledInterrupt == 1) //完成一次中断服务,OLED需清屏
- {
- OLED_Clear();
- OledInterrupt = 0;
- }
- //模式1, 显示2021
- if(MoudleKey == 1)
- {
- OLED_ShowString(48,2,"2021");
- //delay_ms(5); //为了显示转变实时性,不要延时
- }
- //模式2, 显示8.4
- else if(MoudleKey == 2)
- {
- OLED_ShowString(48,2,"8.4");
- //delay_ms(5);
- }
- //模式3, 显示NUEDC Contest
- else if(MoudleKey == 3)
- {
- OLED_ShowString(16,2,"NUEDC Contest");
- //delay_ms(5);
- }
- //模式4, 显示全国大学生电子设计竞赛培训网
- else if(MoudleKey == 4)
- {
- OLED_ShowCHinese(0,2,0); //全
- OLED_ShowCHinese(18,2,1); //国
- OLED_ShowCHinese(36,2,2); //大
- OLED_ShowCHinese(54,2,3); //学
- OLED_ShowCHinese(72,2,4); //生
- OLED_ShowCHinese(90,2,5); //电
- OLED_ShowCHinese(108,2,6); //子
- OLED_ShowCHinese(0,4,7); //设
- OLED_ShowCHinese(18,4,8); //计
- OLED_ShowCHinese(36,4,9); //竞
- OLED_ShowCHinese(54,4,10); //赛
- OLED_ShowCHinese(72,4,11); //培
- OLED_ShowCHinese(90,4,12); //训
- OLED_ShowCHinese(108,4,13); //网
- //delay_ms(5);
- }
- //模式5, 显示电赛徽章
- else if(MoudleKey == 5)
- {
- OLED_DrawBMP(0,0,128,8,BMP1); //1电赛徽章图片显示
- //delay_ms(5);
- }
- //模式6, 显示TI标志
- else if(MoudleKey == 6)
- {
- OLED_DrawBMP(0,0,128,8,BMP4); //4TI标志图片显示
- //delay_ms(5);
- }
- //模式7, 显示欢迎大家报名参加电赛!
- else if(MoudleKey == 7)
- {
- OLED_ShowCHinese(0,2,14); //欢
- OLED_ShowCHinese(18,2,15); //迎
- OLED_ShowCHinese(36,2,16); //大
- OLED_ShowCHinese(54,2,17); //家
- OLED_ShowCHinese(72,2,18); //报
- OLED_ShowCHinese(90,2,19); //名
- OLED_ShowCHinese(0,4,20); //参
- OLED_ShowCHinese(18,4,21); //加
- OLED_ShowCHinese(36,4,22); //电
- OLED_ShowCHinese(54,4,23); //赛
- OLED_ShowCHinese(72,4,24); //!
- //delay_ms(5);
- }
- //模式8, 显示https://www.nuedc-training.com.cn/
- else if(MoudleKey == 8)
- {
- OLED_ShowString(8,0,"https://www.");
- OLED_ShowString(8,2,"nuedc-training.");
- OLED_ShowString(8,4,"com.cn/");
- //delay_ms(5);
- }
- //模式9, 显示4月份网站活动 (2) 分享代码赢板卡
- else if(MoudleKey == 9)
- {
- OLED_ShowChar(0,0,'4'); //4
- OLED_ShowCHinese(18,0,25); //月
- OLED_ShowCHinese(36,0,26); //份
- OLED_ShowCHinese(54,0,27); //网
- OLED_ShowCHinese(72,0,28); //站
- OLED_ShowCHinese(90,0,29); //活
- OLED_ShowCHinese(108,0,30); //动
- OLED_ShowChar(36,2,'('); //(
- OLED_ShowChar(54,2,'2'); //2
- OLED_ShowChar(72,2,')'); //)
- OLED_ShowCHinese(0,4,31); //分
- OLED_ShowCHinese(18,4,32); //享
- OLED_ShowCHinese(36,4,33); //代
- OLED_ShowCHinese(54,4,34); //码
- OLED_ShowCHinese(72,4,35); //赢
- OLED_ShowCHinese(90,4,36); //板
- OLED_ShowCHinese(108,4,37); //卡
- //delay_ms(5);
- }
- //模式10, 显示收藏
- else if(MoudleKey == 10)
- {
- OLED_DrawBMP(0,0,128,8,BMP5); //5收藏图片显示
- //delay_ms(5);
- }
- //模式11, 显示打赏
- else if(MoudleKey == 11)
- {
- OLED_DrawBMP(0,0,128,8,BMP6); //6打赏图片显示
- //delay_ms(5);
- }
- //模式12, 显示投票
- else if(MoudleKey == 12)
- {
- OLED_DrawBMP(0,0,128,8,BMP7); //7投票图片显示
- //delay_ms(5);
- }
- //模式13, 显示重庆大学校徽
- else if(MoudleKey == 13)
- {
- OLED_DrawBMP(0,0,128,8,BMP2); //2图片显示
- //delay_ms(5);
- }
- //模式14, 显示重庆大学
- else if(MoudleKey == 14)
- {
- OLED_DrawBMP(0,0,128,8,BMP3); //3图片显示
- //delay_ms(5);
- }
- //其他模式,
- else
- {
- }
- }
- }
- /* GPIO中断服务程序 */
- /* 在中断中进行列扫描判断哪个按键按下,中断结束将所有列置为0. */
- void PORT5_IRQHandler(void)
- {
- uint32_t status1; //设置一个状态标志量,寄存中断情况
- OledInterrupt = 1; //进入中断服务程序,OledInterrupt置1
- status1 = MAP_GPIO_getEnabledInterruptStatus(GPIO_PORT_P5);
- MAP_GPIO_clearInterruptFlag(GPIO_PORT_P5, status1); //清零所有中断标志位
- //判断第一列按键是否按下,按下输入为0
- ButOutLowC1;
- ButOutHighC2;
- ButOutHighC3;
- ButOutHighC4;
- if(!(MAP_GPIO_getInputPinValue(GPIO_PORT_P5, GPIO_PIN1)) ) //S5按下
- {
- MoudleKey=5;
- }
- else if(!(MAP_GPIO_getInputPinValue(GPIO_PORT_P5, GPIO_PIN2)) ) //S9按下
- {
- MoudleKey=9;
- }
- else if(!(MAP_GPIO_getInputPinValue(GPIO_PORT_P5, GPIO_PIN6)) ) //S13按下
- {
- MoudleKey=13;
- }
- //判断第二列按键是否按下,按下输入为0
- ButOutHighC1;
- ButOutLowC2;
- ButOutHighC3;
- ButOutHighC4;
- if(!(MAP_GPIO_getInputPinValue(GPIO_PORT_P5, GPIO_PIN1)) ) //S6按下
- {
- MoudleKey=6;
- }
- else if(!(MAP_GPIO_getInputPinValue(GPIO_PORT_P5, GPIO_PIN2)) ) //S10按下
- {
- MoudleKey=10;
- }
- else if(!(MAP_GPIO_getInputPinValue(GPIO_PORT_P5, GPIO_PIN6)) ) //S14按下
- {
- MoudleKey=14;
- }
- //判断第三列按键是否按下,按下输入为0
- ButOutHighC1;
- ButOutHighC2;
- ButOutLowC3;
- ButOutHighC4;
- if(!(MAP_GPIO_getInputPinValue(GPIO_PORT_P5, GPIO_PIN1)) ) //S7按下
- {
- MoudleKey=7;
- }
- else if(!(MAP_GPIO_getInputPinValue(GPIO_PORT_P5, GPIO_PIN2)) ) //S11按下
- {
- MoudleKey=11;
- }
- else if(!(MAP_GPIO_getInputPinValue(GPIO_PORT_P5, GPIO_PIN6)) ) //S15按下,模式选择+1,显示下一项内容
- {
- delay_ms(10); //需要延时消抖
- if(MAP_GPIO_getInputPinValue(GPIO_PORT_P5, GPIO_PIN6) )
- if(MoudleKey < 14)
- MoudleKey++;
- }
- //判断第四列按键是否按下,按下输入为0
- ButOutHighC1;
- ButOutHighC2;
- ButOutHighC3;
- ButOutLowC4;
- if(!(MAP_GPIO_getInputPinValue(GPIO_PORT_P5, GPIO_PIN1)) ) //S8按下
- {
- MoudleKey=8;
- }
- else if(!(MAP_GPIO_getInputPinValue(GPIO_PORT_P5, GPIO_PIN2)) ) //S12按下
- {
- MoudleKey=12;
- }
- else if(!(MAP_GPIO_getInputPinValue(GPIO_PORT_P5, GPIO_PIN6)) ) //S16按下,模式选择-1,显示上一项内容
- {
- delay_ms(10); //需要延时消抖
- if(MAP_GPIO_getInputPinValue(GPIO_PORT_P5, GPIO_PIN6) )
- if(MoudleKey > 0)
- MoudleKey--;
- }
- //所有列置0,方便下一次进入中断
- ButOutLowC1;
- ButOutLowC2;
- ButOutLowC3;
- ButOutLowC4;
- }
- void PORT6_IRQHandler(void)
- {
- uint32_t status2; //设置一个状态标志量,寄存中断情况
- OledInterrupt = 1; //进入中断服务程序,OledInterrupt置1
- status2 = MAP_GPIO_getEnabledInterruptStatus(GPIO_PORT_P6);
- MAP_GPIO_clearInterruptFlag(GPIO_PORT_P6, status2); //清零所有中断标志位
- //判断第一列按键是否按下,按下输入为0
- ButOutLowC1;
- ButOutHighC2;
- ButOutHighC3;
- ButOutHighC4;
- if(!(MAP_GPIO_getInputPinValue(GPIO_PORT_P6, GPIO_PIN6)) ) //S1按下
- {
- MoudleKey=1;
- }
- //判断第二列按键是否按下,按下输入为0
- ButOutHighC1;
- ButOutLowC2;
- ButOutHighC3;
- ButOutHighC4;
- if(!(MAP_GPIO_getInputPinValue(GPIO_PORT_P6, GPIO_PIN6)) ) //S2按下
- {
- MoudleKey=2;
- }
- //判断第三列按键是否按下,按下输入为0
- ButOutHighC1;
- ButOutHighC2;
- ButOutLowC3;
- ButOutHighC4;
- if(!(MAP_GPIO_getInputPinValue(GPIO_PORT_P6, GPIO_PIN6)) ) //S3按下
- {
- MoudleKey=3;
- }
- //判断第四列按键是否按下,按下输入为0
- ButOutHighC1;
- ButOutHighC2;
- ButOutHighC3;
- ButOutLowC4;
- if(!(MAP_GPIO_getInputPinValue(GPIO_PORT_P6, GPIO_PIN6)) ) //S4按下
- {
- MoudleKey=4;
- }
- //所有列置0,方便下一次进入中断
- ButOutLowC1;
- ButOutLowC2;
- ButOutLowC3;
- ButOutLowC4;
- }
复制代码
6. 工程文件及OLED资料
矩阵按键切换OLED显示 OLED资料.zip
(6.38 MB, 下载次数: 93)
|