最近在《DSP原理与应用》课程中完成了基于TMS320F2812的GPIO实验内容包括线性键盘控制跑马灯方向与启停以及矩阵键盘独立控制8个LED。在这里把实验过程和代码整理出来希望对学习DSP的小伙伴有所帮助。一、实验概述1.1 实验目的掌握TMS320F2812 GPIO寄存器的配置方法复用功能、方向控制、数据读写理解线性键盘与矩阵键盘的硬件连接及扫描识别原理学习利用GPIO控制LED实现流水灯及独立点亮巩固C语言及CCS开发环境的使用1.2 实验环境硬件SEED-DPS2812M开发板TMS320F2812、XDS510仿真器、PC软件Windows Code Composer Studio (CCS)二、GPIO寄存器基础TMS320F2812的GPIO通过以下几类寄存器配置寄存器功能说明GPxMUX复用控制0→GPIO功能1→外设功能GPxDIR方向控制0→输入1→输出GPxDAT数据寄存器读引脚状态 / 写输出电平GPxSET置位寄存器写1将对应输出引脚置高GPxCLEAR清零寄存器写1将对应输出引脚拉低GPxTOGGLE翻转寄存器写1使输出引脚电平翻转注意GPxMUX和GPxDIR受EALLOW保护修改前需执行EALLOW修改后执行EDIS。三、任务1线性键盘控制跑马灯方向及启停3.1 硬件连接LED输出GPIOA0~A7 → 8个LEDD08~D15按键输入SW1→GPIOB5、SW4→GPIOB4、SW7→GPIOB3扫描输出GPIOB2 输出低电平作为公共扫描线线性键盘原理公共端B2输出低电平分别读取三个输入引脚状态低电平表示该按键被按下。3.2 软件设计思路初始化所有LED熄灭GPIOB20方向初始为从右向左起始点亮最右边LED主循环若run_flag1则点亮当前LED → 延时并扫描按键 → 熄灭当前LED → 根据方向更新下一个LED按键扫描检测SW1/SW4/SW7加入消抖改变方向/启停标志3.3 关键代码// 线性键盘按键对应的 GPIO 引脚输入 #define KEY_SW1 GpioDataRegs.GPBDAT.bit.GPIOB5 // SW1 #define KEY_SW4 GpioDataRegs.GPBDAT.bit.GPIOB4 // SW4 #define KEY_SW7 GpioDataRegs.GPBDAT.bit.GPIOB3 // SW7 // 全局变量 Uint32 current_led; // 当前点亮的LED位 Uint32 direction; // 0:从右向左, 1:从左向右 Uint32 run_flag; // 1:流动, 0:停止 // 线性键盘扫描函数 void Scan_Key(void) { Uint32 i; if(KEY_SW1 0) { for(i0; i10000; i); // 消抖 if(KEY_SW1 0) { direction 0; // 从右向左 current_led 0x0080; // 最右边LED run_flag 1; while(KEY_SW1 0); // 等待释放 } } else if(KEY_SW4 0) { // 类似处理direction1current_led0x0001 } else if(KEY_SW7 0) { // 停止run_flag0但保持当前LED点亮 } }3.4 GPIO配置关键部分cvoid Gpio_select(void) { EALLOW; GpioMuxRegs.GPAMUX.all 0x0000; // GPIOA全部为GPIO GpioMuxRegs.GPBMUX.all 0x0000; GpioMuxRegs.GPADIR.all 0xFFFF; // GPIOA全部输出LED // GPIOB: B0~B1输出B2输出(扫描线)B3~B5输入(按键) GpioMuxRegs.GPBDIR.all 0xFFC7; // 1111 1111 1100 0111 EDIS; }3.5 实验现象按下SW1跑马灯从右向左循环流动按下SW4方向立即切换为从左向右按下SW7跑马灯停止当前LED保持点亮再次按SW1/SW4恢复流动四、任务2矩阵键盘控制LED独立点亮4.1 硬件连接LED输出GPIOA0~A7与任务1相同矩阵键盘行输入GPIOB5行0、GPIOB4行1、GPIOB3行2列输出GPIOB2列0、GPIOB1列1、GPIOB0列2采用3×3矩阵键盘SW1~SW9使用列扫描法。4.2 扫描流程所有列线输出高电平依次将某一列置低其余列保持高读取三根行线状态若某行为低则记录行号延时5ms消抖再次确认该行仍为低计算键值key row*3 col 1范围1~9映射到LED键值1~8点亮对应LEDGPIOA0~A7键值9熄灭所有LED4.3 关键代码// 行输入定义 #define ROW0 GpioDataRegs.GPBDAT.bit.GPIOB5 #define ROW1 GpioDataRegs.GPBDAT.bit.GPIOB4 #define ROW2 GpioDataRegs.GPBDAT.bit.GPIOB3 // 列输出定义 #define COL0 GpioDataRegs.GPBDAT.bit.GPIOB2 #define COL1 GpioDataRegs.GPBDAT.bit.GPIOB1 #define COL2 GpioDataRegs.GPBDAT.bit.GPIOB0 Uint16 Scan_Key(void) { Uint16 col, row; // 所有列输出高 COL0 1; COL1 1; COL2 1; Delay_us(20); for(col 0; col 3; col) { // 当前列置低 if(col 0) { COL0 0; COL1 1; COL2 1; } else if(col 1) { COL0 1; COL1 0; COL2 1; } else { COL0 1; COL1 1; COL2 0; } Delay_us(50); // 读取行状态 if(ROW0 0) row 0; else if(ROW1 0) row 1; else if(ROW2 0) row 2; else continue; // 消抖确认 Delay_ms(5); // 再次设置当前列并读取行 if( (row0 ROW00) || (row1 ROW10) || (row2 ROW20) ) { return row*3 col 1; // 返回键值1~9 } } return 0; // 无按键 } void Set_LED(Uint16 key) { if(key 1 key 8) { Uint16 led_bit 1 (key - 1); GpioDataRegs.GPASET.all led_bit; // 只点亮对应LED } else if(key 9) { GpioDataRegs.GPACLEAR.all 0x00FF; // 熄灭所有LED } }4.4 实验现象按下SW1~SW8对应编号的LED独立点亮互不影响按下SW9所有LED熄灭五、实验总结与心得寄存器保护初次忘记EALLOW导致无法修改方向寄存器排查后印象深刻。按键消抖机械按键必须加入软件消抖延时二次确认否则会出现误触发或多重触发。GPxSET/GPxCLEAR相比直接操作GPxDAT使用置位/清零寄存器可以避免读-改-写的风险且不影响其他引脚状态。矩阵扫描效率列扫描法简单可靠注意每次切换列后需要短暂延时等待电平稳定。本实验为后续使用DSP驱动LCD、步进电机等外设打下了很好的GPIO操作基础。六、代码获取直接解压复制代码到您的CCS工程main.c文件中注意包含必要的头文件即可。七、参考资料TMS320F2812 Datasheet Technical Reference Manual《DSP原理与应用》课程讲义SEED-DPS2812M开发板原理图