[MSP-EXP432P401R] MSP432P401R通过矩阵按键切换SSD1306 OLED显示内容

  [复制链接]

4

主题

13

帖子

685

积分

单晶硅锭

Rank: 3Rank: 3

积分
685
查看: 3793回复: 3 发表于 2021-4-21 11:33:09   只看该作者
第3题:菜单功能,按键+显示
1.在第2题的基础上,增加按键切换显示的功能,每次按键变换一次显示
2.可以通过输入数字,显示特定的内容;

************************************************************************************************
1.硬件说明
2.硬件连接
3.功能描述
4. CCS10.1.1使用小知识
5.程序代码
6. 工程文件及OLED资料
***********************************************************************************************************************
1.硬件说明

开发板:MSP432P401R LAUNCHPAD
开发环境:CCS10.1.1
矩阵按键:

矩阵按键正面

矩阵按键正面
      

矩阵按键反面

矩阵按键反面

SSD1306 OLED显示屏:

OLED正面

OLED正面
            

OLED反面

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 ”,

1

1


* 按下按键S2,OLED上显示“ 8.4 ”,

2

2


* 按下按键S3,OLED上显示“ NUEDC Contest ”,

3

3


* 按下按键S4,OLED上显示“ 全国大学生电子设计竞赛培训网 ”,

4

4


* 按下按键S5,OLED上显示“ 全国大学生电子设计竞赛徽章 ”,

5

5


* 按下按键S6,OLED上显示“ TI公司标志 ”,

6

6


* 按下按键S7,OLED上显示“ 欢迎大家报名参加电赛! ”,

7

7


* 按下按键S8,OLED上显示“ https://www.nuedc-training.com.cn/ ”,

8

8


* 按下按键S9,OLED上显示“ 4月份网站活动 (2) 分享代码赢板卡 ”,

9

9


* 按下按键S10,OLED上显示“ 收藏图标 ”,

10

10


* 按下按键S11,OLED上显示“ 打赏图标 ”,

11

11


* 按下按键S12,OLED上显示“ 投票图标 ”,

12

12


* 按下按键S13,OLED上显示“ 重庆大学校徽 ”,

13

13


* 按下按键S14,OLED上显示“ 重庆大学 ”,

14

14


* 按下按键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内容
  1. #include <ti/devices/msp432p4xx/driverlib/driverlib.h>
  2. #include <stdint.h>
  3. #include <stdbool.h>
  4. #include"oled.h"
  5. #include"bmp.h"


  6. #define ButOutHighC1 {MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P2, GPIO_PIN4);} //第1列C1输出高电平
  7. #define ButOutLowC1 {MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN4);} //第1列C1输出低电平
  8. #define ButOutHighC2 {MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P2, GPIO_PIN5);} //第2列C2输出高电平
  9. #define ButOutLowC2 {MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN5);} //第2列C2输出低电平
  10. #define ButOutHighC3 {MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P2, GPIO_PIN6);} //第3列C3输出高电平
  11. #define ButOutLowC3 {MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN6);} //第3列C3输出低电平
  12. #define ButOutHighC4 {MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P2, GPIO_PIN7);} //第4列C4输出高电平
  13. #define ButOutLowC4 {MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN7);} //第4列C4输出低电平

  14. uint32_t MoudleKey=0; //模式选择参数,第几个按键按下对应第几个OLED模式

  15. /*中断输入标志参数OledInterrupt。有按键按下则OLED需清屏重新显示,进入中断服务函数,OledInterrupt被置1;
  16. * 返回循环,OLED清屏,OledInterrupt被清0。避免OLED显示内容覆盖。*/
  17. int OledInterrupt =0;

  18. int main(void)
  19. {
  20. init(); //OLED端口定义
  21. OLED_Init(); //初始化SSD1306 OLED
  22. //配置列信号作为输出
  23. MAP_GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN4); //第1列C1
  24. MAP_GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN5); //第2列C2
  25. MAP_GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN6); //第3列C3
  26. MAP_GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN7); //第4列C4

  27. //所有列输出低电平
  28. ButOutLowC1;
  29. ButOutLowC2;
  30. ButOutLowC3;
  31. ButOutLowC4;

  32. //配置第1行R1--P6.6为上拉电阻输入并使能中断,按键R1接P5.0,灵敏度太低
  33. MAP_GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P6, GPIO_PIN6);
  34. MAP_GPIO_clearInterruptFlag(GPIO_PORT_P6, GPIO_PIN6);
  35. MAP_GPIO_enableInterrupt(GPIO_PORT_P6, GPIO_PIN6);
  36. MAP_Interrupt_enableInterrupt(INT_PORT6);

  37. //配置第2行R2--P5.1为上拉电阻输入并使能中断
  38. MAP_GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P5, GPIO_PIN1);
  39. MAP_GPIO_clearInterruptFlag(GPIO_PORT_P5, GPIO_PIN1);
  40. MAP_GPIO_enableInterrupt(GPIO_PORT_P5, GPIO_PIN1);

  41. //配置第3行R3--P5.2为上拉电阻输入并使能中断
  42. MAP_GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P5, GPIO_PIN2);
  43. MAP_GPIO_clearInterruptFlag(GPIO_PORT_P5, GPIO_PIN2);
  44. MAP_GPIO_enableInterrupt(GPIO_PORT_P5, GPIO_PIN2);

  45. //配置第4行R4--P5.6为上拉电阻输入并使能中断
  46. MAP_GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P5, GPIO_PIN6);
  47. MAP_GPIO_clearInterruptFlag(GPIO_PORT_P5, GPIO_PIN6);
  48. MAP_GPIO_enableInterrupt(GPIO_PORT_P5, GPIO_PIN6);
  49. MAP_Interrupt_enableInterrupt(INT_PORT5);

  50. //Enabling SRAM Bank Retention
  51. MAP_SysCtl_enableSRAMBankRetention(SYSCTL_SRAM_BANK1);

  52. //使能全局中断
  53. MAP_Interrupt_enableMaster();

  54. // MAP_WDT_A_holdTimer(); //关闭看门狗

  55. //进入模式选择循环
  56. while (1)
  57. {
  58. if( OledInterrupt == 1) //完成一次中断服务,OLED需清屏
  59. {
  60. OLED_Clear();
  61. OledInterrupt = 0;
  62. }

  63. //模式1, 显示2021
  64. if(MoudleKey == 1)
  65. {
  66. OLED_ShowString(48,2,"2021");
  67. //delay_ms(5); //为了显示转变实时性,不要延时
  68. }

  69. //模式2, 显示8.4
  70. else if(MoudleKey == 2)
  71. {
  72. OLED_ShowString(48,2,"8.4");
  73. //delay_ms(5);
  74. }

  75. //模式3, 显示NUEDC Contest
  76. else if(MoudleKey == 3)
  77. {
  78. OLED_ShowString(16,2,"NUEDC Contest");
  79. //delay_ms(5);
  80. }

  81. //模式4, 显示全国大学生电子设计竞赛培训网
  82. else if(MoudleKey == 4)
  83. {
  84. OLED_ShowCHinese(0,2,0); //全
  85. OLED_ShowCHinese(18,2,1); //国
  86. OLED_ShowCHinese(36,2,2); //大
  87. OLED_ShowCHinese(54,2,3); //学
  88. OLED_ShowCHinese(72,2,4); //生
  89. OLED_ShowCHinese(90,2,5); //电
  90. OLED_ShowCHinese(108,2,6); //子
  91. OLED_ShowCHinese(0,4,7); //设
  92. OLED_ShowCHinese(18,4,8); //计
  93. OLED_ShowCHinese(36,4,9); //竞
  94. OLED_ShowCHinese(54,4,10); //赛
  95. OLED_ShowCHinese(72,4,11); //培
  96. OLED_ShowCHinese(90,4,12); //训
  97. OLED_ShowCHinese(108,4,13); //网
  98. //delay_ms(5);
  99. }

  100. //模式5, 显示电赛徽章
  101. else if(MoudleKey == 5)
  102. {
  103. OLED_DrawBMP(0,0,128,8,BMP1); //1电赛徽章图片显示
  104. //delay_ms(5);
  105. }

  106. //模式6, 显示TI标志
  107. else if(MoudleKey == 6)
  108. {
  109. OLED_DrawBMP(0,0,128,8,BMP4); //4TI标志图片显示
  110. //delay_ms(5);
  111. }

  112. //模式7, 显示欢迎大家报名参加电赛!
  113. else if(MoudleKey == 7)
  114. {
  115. OLED_ShowCHinese(0,2,14); //欢
  116. OLED_ShowCHinese(18,2,15); //迎
  117. OLED_ShowCHinese(36,2,16); //大
  118. OLED_ShowCHinese(54,2,17); //家
  119. OLED_ShowCHinese(72,2,18); //报
  120. OLED_ShowCHinese(90,2,19); //名
  121. OLED_ShowCHinese(0,4,20); //参
  122. OLED_ShowCHinese(18,4,21); //加
  123. OLED_ShowCHinese(36,4,22); //电
  124. OLED_ShowCHinese(54,4,23); //赛
  125. OLED_ShowCHinese(72,4,24); //!
  126. //delay_ms(5);
  127. }

  128. //模式8, 显示https://www.nuedc-training.com.cn/
  129. else if(MoudleKey == 8)
  130. {
  131. OLED_ShowString(8,0,"https://www.");
  132. OLED_ShowString(8,2,"nuedc-training.");
  133. OLED_ShowString(8,4,"com.cn/");
  134. //delay_ms(5);
  135. }

  136. //模式9, 显示4月份网站活动 (2) 分享代码赢板卡
  137. else if(MoudleKey == 9)
  138. {
  139. OLED_ShowChar(0,0,'4'); //4
  140. OLED_ShowCHinese(18,0,25); //月
  141. OLED_ShowCHinese(36,0,26); //份
  142. OLED_ShowCHinese(54,0,27); //网
  143. OLED_ShowCHinese(72,0,28); //站
  144. OLED_ShowCHinese(90,0,29); //活
  145. OLED_ShowCHinese(108,0,30); //动
  146. OLED_ShowChar(36,2,'('); //(
  147. OLED_ShowChar(54,2,'2'); //2
  148. OLED_ShowChar(72,2,')'); //)
  149. OLED_ShowCHinese(0,4,31); //分
  150. OLED_ShowCHinese(18,4,32); //享
  151. OLED_ShowCHinese(36,4,33); //代
  152. OLED_ShowCHinese(54,4,34); //码
  153. OLED_ShowCHinese(72,4,35);  //赢
  154. OLED_ShowCHinese(90,4,36); //板
  155. OLED_ShowCHinese(108,4,37); //卡
  156. //delay_ms(5);
  157. }

  158. //模式10, 显示收藏
  159. else if(MoudleKey == 10)
  160. {
  161. OLED_DrawBMP(0,0,128,8,BMP5); //5收藏图片显示
  162. //delay_ms(5);
  163. }

  164. //模式11, 显示打赏
  165. else if(MoudleKey == 11)
  166. {
  167. OLED_DrawBMP(0,0,128,8,BMP6); //6打赏图片显示
  168. //delay_ms(5);
  169. }

  170. //模式12, 显示投票
  171. else if(MoudleKey == 12)
  172. {
  173. OLED_DrawBMP(0,0,128,8,BMP7); //7投票图片显示
  174. //delay_ms(5);
  175. }

  176. //模式13, 显示重庆大学校徽
  177. else if(MoudleKey == 13)
  178. {
  179. OLED_DrawBMP(0,0,128,8,BMP2); //2图片显示
  180. //delay_ms(5);
  181. }

  182. //模式14, 显示重庆大学
  183. else if(MoudleKey == 14)
  184. {
  185. OLED_DrawBMP(0,0,128,8,BMP3); //3图片显示
  186. //delay_ms(5);
  187. }

  188. //其他模式,
  189. else
  190. {


  191. }


  192. }
  193. }


  194. /* GPIO中断服务程序 */
  195. /* 在中断中进行列扫描判断哪个按键按下,中断结束将所有列置为0. */

  196. void PORT5_IRQHandler(void)
  197. {
  198. uint32_t status1; //设置一个状态标志量,寄存中断情况
  199. OledInterrupt = 1; //进入中断服务程序,OledInterrupt置1
  200. status1 = MAP_GPIO_getEnabledInterruptStatus(GPIO_PORT_P5);
  201. MAP_GPIO_clearInterruptFlag(GPIO_PORT_P5, status1); //清零所有中断标志位

  202. //判断第一列按键是否按下,按下输入为0
  203. ButOutLowC1;
  204. ButOutHighC2;
  205. ButOutHighC3;
  206. ButOutHighC4;
  207. if(!(MAP_GPIO_getInputPinValue(GPIO_PORT_P5, GPIO_PIN1)) ) //S5按下
  208. {
  209. MoudleKey=5;

  210. }
  211. else if(!(MAP_GPIO_getInputPinValue(GPIO_PORT_P5, GPIO_PIN2)) ) //S9按下
  212. {
  213. MoudleKey=9;

  214. }
  215. else if(!(MAP_GPIO_getInputPinValue(GPIO_PORT_P5, GPIO_PIN6)) ) //S13按下
  216. {
  217. MoudleKey=13;

  218. }

  219. //判断第二列按键是否按下,按下输入为0
  220. ButOutHighC1;
  221. ButOutLowC2;
  222. ButOutHighC3;
  223. ButOutHighC4;
  224. if(!(MAP_GPIO_getInputPinValue(GPIO_PORT_P5, GPIO_PIN1)) ) //S6按下
  225. {
  226. MoudleKey=6;

  227. }
  228. else if(!(MAP_GPIO_getInputPinValue(GPIO_PORT_P5, GPIO_PIN2)) ) //S10按下
  229. {
  230. MoudleKey=10;

  231. }
  232. else if(!(MAP_GPIO_getInputPinValue(GPIO_PORT_P5, GPIO_PIN6)) ) //S14按下
  233. {
  234. MoudleKey=14;

  235. }

  236. //判断第三列按键是否按下,按下输入为0
  237. ButOutHighC1;
  238. ButOutHighC2;
  239. ButOutLowC3;
  240. ButOutHighC4;
  241. if(!(MAP_GPIO_getInputPinValue(GPIO_PORT_P5, GPIO_PIN1)) ) //S7按下
  242. {
  243. MoudleKey=7;

  244. }
  245. else if(!(MAP_GPIO_getInputPinValue(GPIO_PORT_P5, GPIO_PIN2)) ) //S11按下
  246. {
  247. MoudleKey=11;

  248. }
  249. else if(!(MAP_GPIO_getInputPinValue(GPIO_PORT_P5, GPIO_PIN6)) ) //S15按下,模式选择+1,显示下一项内容
  250. {
  251. delay_ms(10); //需要延时消抖
  252. if(MAP_GPIO_getInputPinValue(GPIO_PORT_P5, GPIO_PIN6) )
  253. if(MoudleKey < 14)
  254. MoudleKey++;
  255. }

  256. //判断第四列按键是否按下,按下输入为0
  257. ButOutHighC1;
  258. ButOutHighC2;
  259. ButOutHighC3;
  260. ButOutLowC4;
  261. if(!(MAP_GPIO_getInputPinValue(GPIO_PORT_P5, GPIO_PIN1)) ) //S8按下
  262. {
  263. MoudleKey=8;

  264. }
  265. else if(!(MAP_GPIO_getInputPinValue(GPIO_PORT_P5, GPIO_PIN2)) ) //S12按下
  266. {
  267. MoudleKey=12;

  268. }
  269. else if(!(MAP_GPIO_getInputPinValue(GPIO_PORT_P5, GPIO_PIN6)) ) //S16按下,模式选择-1,显示上一项内容
  270. {
  271. delay_ms(10); //需要延时消抖
  272. if(MAP_GPIO_getInputPinValue(GPIO_PORT_P5, GPIO_PIN6) )
  273. if(MoudleKey > 0)
  274. MoudleKey--;

  275. }

  276. //所有列置0,方便下一次进入中断
  277. ButOutLowC1;
  278. ButOutLowC2;
  279. ButOutLowC3;
  280. ButOutLowC4;
  281. }

  282. void PORT6_IRQHandler(void)
  283. {
  284. uint32_t status2; //设置一个状态标志量,寄存中断情况
  285. OledInterrupt = 1; //进入中断服务程序,OledInterrupt置1
  286. status2 = MAP_GPIO_getEnabledInterruptStatus(GPIO_PORT_P6);
  287. MAP_GPIO_clearInterruptFlag(GPIO_PORT_P6, status2); //清零所有中断标志位

  288. //判断第一列按键是否按下,按下输入为0
  289. ButOutLowC1;
  290. ButOutHighC2;
  291. ButOutHighC3;
  292. ButOutHighC4;
  293. if(!(MAP_GPIO_getInputPinValue(GPIO_PORT_P6, GPIO_PIN6)) ) //S1按下
  294. {
  295. MoudleKey=1;

  296. }

  297. //判断第二列按键是否按下,按下输入为0
  298. ButOutHighC1;
  299. ButOutLowC2;
  300. ButOutHighC3;
  301. ButOutHighC4;
  302. if(!(MAP_GPIO_getInputPinValue(GPIO_PORT_P6, GPIO_PIN6)) ) //S2按下
  303. {
  304. MoudleKey=2;

  305. }

  306. //判断第三列按键是否按下,按下输入为0
  307. ButOutHighC1;
  308. ButOutHighC2;
  309. ButOutLowC3;
  310. ButOutHighC4;
  311. if(!(MAP_GPIO_getInputPinValue(GPIO_PORT_P6, GPIO_PIN6)) ) //S3按下
  312. {
  313. MoudleKey=3;

  314. }

  315. //判断第四列按键是否按下,按下输入为0
  316. ButOutHighC1;
  317. ButOutHighC2;
  318. ButOutHighC3;
  319. ButOutLowC4;
  320. if(!(MAP_GPIO_getInputPinValue(GPIO_PORT_P6, GPIO_PIN6)) ) //S4按下
  321. {
  322. MoudleKey=4;

  323. }

  324. //所有列置0,方便下一次进入中断
  325. ButOutLowC1;
  326. ButOutLowC2;
  327. ButOutLowC3;
  328. ButOutLowC4;
  329. }
复制代码


6. 工程文件及OLED资料
矩阵按键切换OLED显示 OLED资料.zip (6.38 MB, 下载次数: 92)

打赏

参与人数 12赫兹币 +60 收起 理由
blueblues + 5
RHAnthony + 5
JTao + 5
shenweizuibang + 5
黄福均 + 5
hw123456 + 5
csj0710 + 5
zombiejbt + 5
mei187 + 5
fu188 + 5
hu158 + 5
lithiumice + 5

查看全部打赏

0

主题

1

帖子

62

积分

一粒轻沙

Rank: 1

积分
62
发表于 2021-4-23 12:01:16   只看该作者
学长好棒

73

主题

469

帖子

1005

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1005
发表于 2021-4-27 14:12:41   只看该作者
感谢分享

0

主题

1

帖子

83

积分

一粒轻沙

Rank: 1

积分
83
发表于 2022-7-21 15:57:43   只看该作者

编译出错。
快速回复 返回顶部 返回列表