LED裸机程序开发
本小结将讲解如何利用TI提供的StarterWare软件包开发一个基于DSP C6748的LED流水灯程序,以及如何查找芯片的技术参考手册和数据手册。文章内容主要涵盖LED裸机程序开发、工程建立、添加头文件和库文件、源代码编写和解析和按键中断裸机程序演示和解析等。
关于如何操作CCS、配置仿真器、烧写程序等,请查看《TMS320C6748开发案例使用手册》的内容。本教程只是配合《TMS320C6748开发案例使用手册》对基本的GPIO操作进行指导性的说明。具体程序内容可能因我司案例更新有差异,以实际案例为准。
本篇文章主要讲解硬件开发中,如何使用Matlab生成可供TMS320C6748开发板(测试板卡)使用的算法,内容包含有快速入门、安装Matlab、编写函数M文件、验证算法、生成/使用/测试代码、进阶指南等,欢迎嵌入式开发相关用户阅读与分享。
测试板卡为创龙科技TL6748-EVM开发板,它是一款基于TI TMS320C6748定点/浮点DSP C674x处理器设计的开发板,由核心板和底板组成。核心板经过专业的PCB Layout和高低温测试验证,稳定可靠,可满足各种工业应用环境。开发板接口资源丰富,引出网口、uPP、EMIFA、SATA、USB、LCD、VGA等接口,方便用户快速进行产品方案评估与技术预研。
工程建立
产品资料中提供DSP LED程序镜像和源码,路径为:
GPIO_LED.out:DemoStarterWareBinaryGPIO_LED.out //DSP镜像
main.c:DemoStarterWareApplicationGPIO_LEDmain.c //DSP程序源码
在工程建立前,请先使用GEL文件配合仿真器连接DSP核,具体步骤参考《TMS320C6748开发案例使用手册》的开发准备、工程建立、程序加载与固化等等步骤。然后点击“File -> New -> Project -> CCS Project”,然后点击Next,弹出对话框,并修改,如下所示。
图 1
Target:C674x Floating-point DSP->TMS320C6748;选择芯片
Project name:LED;CCS工程名字
在"Empty Projects"下方选择"Empty Project(with main.c)",点击Finish就可以完成工程新建了,弹出如下界面。
图 2
添加头文件和库文件
将StarterWare安装路径下的include目录复制到LED工程的工作目录下。include目录的内容是TMS320C6748开发所需的头文件。LED的工程目录在新建工程时已经设置好工作目录了,例如本例的默认路径,如下图所示。
图 3
在LED工程的工作目录中新建库文件的存放目录library,然后将StarterWare安装路径下的如下文件复制到新建的library目录中。
binaryc674xcgt_ccsc6748driversDebugdrivers.lib
binaryc674xcgt_ccsc6748system_configDebugsystem_config.lib
drivers.lib是TMS320C6748一般外设开发所需的库文件,其源码在StarterWare的drivers目录下。比如StarterWare的include目录下的头文件“gpio.h”,里面有很多相关函数声明,具体实现都是在StarterWare的drivers目录下的“gpio.c”文件里面。
设置编译参数
右击工程,在弹出的菜单中点击Properties(属性),如下图所示。
图 4
在弹出的对话框中点击General,在“Output format”处选择“abi(ELF)”,表明DSP程序的输出镜像的格式是ELF(StarterWare的库默认编译的是ELF文件),数据存取格式是小端模式,如下图所示。
图 5
点击“Build -> C6000 Compiler -> Include Options”,弹出如下界面。
图 6
点击右边的
符号添加包含的头文件路径,弹出如下对话框。
图 7
在空白处先后两次输入“../include”和“../include/hw”,解析如下。
../include:gpio.h头文件所在路径,工程目录下的include目录,LED程序程序将用到。
../include/hw:hw_types.h和其他头文件所在路径,工程目录下的“include/hw”目录,LED程序程序将用到。
增加后如下图所示。
图 8
点击OK,完成编译参数设置。
源代码编写和解析
将产品资料"DemoStarterWareApplicationGPIO_LED"目录下的程序源码main.c的内容复制到工程的main.c文件中,或直接用文件覆盖。CCS中设置为12号字体时,中文注释会比较美观,程序源码解析如下。
/****************************************************************************/
/* */
/* 底板 LED 测试 */
/* */
/* 2014年04月20日 */
/* */
/****************************************************************************/
#include "TL6748.h" // 创龙 DSP6748 开发板相关声明
#include "hw_types.h" // 宏命令
#include "hw_syscfg0_C6748.h" // 系统配置模块寄存器
#include "soc_C6748.h" // DSP C6748 外设寄存器
#include "psc.h" // 电源与睡眠控制宏及设备抽象层函数声明
#include "gpio.h" // 通用输入输出口宏及设备抽象层函数声明
/****************************************************************************/
/* */
/* 宏定义 */
/* */
/****************************************************************************/
// 软件断点
#define SW_BREAKPOINT asm(" SWBP 0 ");
/****************************************************************************/
/* */
/* 全局变量 */
/* */
/****************************************************************************/
/****************************************************************************/
/* */
/* 函数声明 */
/* */
/****************************************************************************/
// 外设使能配置
void PSCInit(void);
// GPIO 管脚复用配置
void GPIOBankPinMuxSet();
// GPIO 管脚初始化
void GPIOBankPinInit();
// 延时
void Delay(unsigned int n);
/****************************************************************************/
/* */
/* 主函数 */
/* */
/****************************************************************************/
int main(void)
{
// 外设使能配置
PSCInit();
// GPIO 管脚复用配置
GPIOBankPinMuxSet();
// GPIO 管脚初始化
GPIOBankPinInit();
// 主循环
for(;;)
{
// 延时
Delay(0x00FFFFFF);
GPIOPinWrite(SOC_GPIO_0_REGS, 3, GPIO_PIN_LOW); // D10 灭 GPIO0[2]
GPIOPinWrite(SOC_GPIO_0_REGS, 1, GPIO_PIN_HIGH); // D7 亮 GPIO0[0]
// 延时
Delay(0x00FFFFFF);
GPIOPinWrite(SOC_GPIO_0_REGS, 1, GPIO_PIN_LOW); // D7 灭 GPIO0[0]
GPIOPinWrite(SOC_GPIO_0_REGS, 6, GPIO_PIN_HIGH); // D6 亮 GPIO0[5]
// 延时
Delay(0x00FFFFFF);
GPIOPinWrite(SOC_GPIO_0_REGS, 6, GPIO_PIN_LOW); // D6 灭 GPIO0[5]
GPIOPinWrite(SOC_GPIO_0_REGS, 2, GPIO_PIN_HIGH); // D9 亮 GPIO0[1]
// 延时
Delay(0x00FFFFFF);
GPIOPinWrite(SOC_GPIO_0_REGS, 2, GPIO_PIN_LOW); // D9 灭 GPIO0[1]
GPIOPinWrite(SOC_GPIO_0_REGS, 3, GPIO_PIN_HIGH); // D10 亮 GPIO0[2]
}
}
/****************************************************************************/
/* */
/* PSC 初始化 */
/* */
/****************************************************************************/
void PSCInit(void)
{
// 使能 GPIO 模块
// 对相应外设模块的使能也可以在 BootLoader 中完成
PSCModuleControl(SOC_PSC_1_REGS, HW_PSC_GPIO, PSC_POWERDOMAIN_ALWAYS_ON, PSC_MDCTL_NEXT_ENABLE);
}
/****************************************************************************/
/* */
/* GPIO 管脚复用配置 */
/* */
/****************************************************************************/
void GPIOBankPinMuxSet(void)
{
// 配置相应的 GPIO 口功能为普通输入输出口
// 底板 LED
GPIOBank0Pin0PinMuxSetup();
GPIOBank0Pin1PinMuxSetup();
GPIOBank0Pin2PinMuxSetup();
GPIOBank0Pin5PinMuxSetup();
}
/****************************************************************************/
/* */
/* GPIO 管脚初始化 */
/* */
/****************************************************************************/
void GPIOBankPinInit(void)
{
// 配置 LED 对应管脚为输出管脚
// OMAPL138 及 DSP C6748 共有 144 个 GPIO
// 以下为各组 GPIO BANK 起始管脚对应值
// 范围 1-144
// GPIO0[0] 1
// GPIO1[0] 17
// GPIO2[0] 33
// GPIO3[0] 49
// GPIO4[0] 65
// GPIO5[0] 81
// GPIO6[0] 97
// GPIO7[0] 113
// GPIO8[0] 129
// 核心板 LED
GPIODirModeSet(SOC_GPIO_0_REGS, 109, GPIO_DIR_OUTPUT); // GPIO6[12]
GPIODirModeSet(SOC_GPIO_0_REGS, 110, GPIO_DIR_OUTPUT); // GPIO6[13]
// 底板 LED
GPIODirModeSet(SOC_GPIO_0_REGS, 1, GPIO_DIR_OUTPUT); // D7 GPIO0[0]
GPIODirModeSet(SOC_GPIO_0_REGS, 2, GPIO_DIR_OUTPUT); // D9 GPIO0[1]
GPIODirModeSet(SOC_GPIO_0_REGS, 3, GPIO_DIR_OUTPUT); // D10 GPIO0[2]
GPIODirModeSet(SOC_GPIO_0_REGS, 6, GPIO_DIR_OUTPUT); // D6 GPIO0[5]
}
/****************************************************************************/
/* */
/* 延时 */
/* */
/****************************************************************************/
void Delay(unsigned int n)
{
unsigned int i;
for(i=n;i>0;i--);
}
以上是GPIO_LED流水灯控制程序,对于GPIO的操作,操作步骤如下。
- 查看评估底板的原理图,找到与LED连接的GPIO编号。
评估底板与LED连接的GPIO分别是GPIO0[1]、GPIO0[2]、GPIO0[5],如下图所示。
图 9
- 首先对处理器的PSC控制进行初始化,使用StarterWare的psc.h头文件提供的PSCModuleControl()来进行控制,因为PSC控制器涉及到较多的内容,这里仅对GPIO_LED这个案例的用法含义做说明,后面各个寄存器说明也是。详细信息请自行查看TMS320C6748的数据手册和技术参考手册。
向PSCModuleControl()传入GPIO的PSC寄存器地址,即SOC_PSC_1_REGS,基于HW_PSC_GPIO这个值做一个偏移到实际GPIO的PSC控制位,PSC_POWERDOMAIN_ALWAYS_ON和PSC_MDCTL_NEXT_ENABLE都是使能PSC相关的控制位,如下图所示。
图 10
PSCModuleControl()函数在psc.h头文件有申明其原型,如下图所示。
图 11
SOC_PSC_1_REGS定义了PSC1控制器的基址,可以在产品资料“Datasheet核心板元器件CPU”目录下《TMS320C6748 Fixed- and Floating-Point DSP datasheet (Rev. G)》数据手册查到数据,如下图所示。
图 12
图 13
图 14
PSC中的GPIO控制在PSC1中的LPSC号码是3,HW_PSC_GPIO定义为3,如下图所示。
图 15
图 16
图 17
PSC_POWERDOMAIN_ALWAYS_ON设置PSC控制器PTCMD、PTSTAT相应的位,在技术参考手册有具体说明,如下图所示。
图 18
图 19
图 20
图 21
- 查看TMS320C6748的数据手册,查找GPIO_LED对应的管脚的PINMUX寄存器的地址,将对应的管脚的寄存器中相应位设置为GPIO的工作模式。
为方便用户开发,我司已将GPIO复用等配置操作直接封装成了函数,用户如需使用,可以直接包含"TL6748.h"文件,并将产品资料"DemoStarterWareApplicationPlatform"下的源码复制到用户当前工程文件夹内即可。这里GPIO复用配置的函数是GPIOBankXPinXPinMuxSetup(),如下图所示。
图 22
本案例中实际是使用StarterWare的库函数HWREG(x)来设置PINMUX的寄存器地址值,用户可以自行查看产品资料"DemoStarterWareApplicationPlatformGPIO.c",其具体的配置例如:HWREG(SOC_SYSCFG_0_REGS SYSCFG0_PINMUX(1))。
HWREG(x)可以在"include/hw/"目录下中hw_types.h头文件查看定义,如下图所示。
图 23
SOC_SYSCFG_0_REGS是PINMUX的基地址,可以在"include/hw/"目录下的soc_C6748.h头文件查看定义,如下图所示。
图 24
可以看出SOC_SYSCFG_0_REGS的值为0x01C14000,类似的地址都可以在《TMS320C6748 Fixed- and Floating-Point DSP datasheet (Rev. G)》数据手册中找到,下图为数据手册中SYSCFG0寄存器基址、结束地址、长度等信息。
图 25
图 26
SYSCFG0_PINMUX(1)是PINMUX1的偏移地址,可以在"includehw"目录下hw_syscfg0_C6748.h头文件查看定义,如下图所示。
图 27
可以算出PINMUX1的偏移地址为0x124,那么可以算出PINMUX1的值为:PINMUX1=(0x01C14000 0x124)=0x01C14124。
具体的地址可以在产品资料“Datasheet核心板元器件CPU”目录下《TMS320C6748 DSP (Rev. C)》技术参考手册查到PINMUX1的值。
图 28
图 29
- 设置GPIO的方向寄存器。
本案例中使用StarterWare的库函数GPIODirModeSet()将GPIO口配置为输出,例如:GPIODirModeSet(SOC_GPIO_0_REGS, 1, GPIO_DIR_OUTPUT)。
GPIODirModeSet()在include目录下gpio.h头文件查看定义,如下图所示。
图 30
SOC_GPIO_0_REGS是GPIO的基地址,在"includehw"目录下soc_C6748.h头文件查看定义,如下图所示。
图 31
可以看出SOC_GPIO_0_REGS的值为0x01E26000,类似的地址都可以在《TMS320C6748 Fixed- and Floating-Point DSP datasheet (Rev. G)》数据手册查到数据,下图为数据手册中GPIO基地址的值。
图 32
图 33
第二个参数“1”是GPIO0[0]的编号,以下为各组GPIO第一个管脚的对应值(范围1~144):GPIO0[0~15]=1~16,GPIO1[0~15]=17~32,GPIO2[0~15]=33~48,GPIO3[0~15]=49~64,GPIO4[0~15]=65~80,GPIO5[0~15]=81~96,GPIO6[0~15]=97~112,GPIO7[0~15]=113~128,GPIO8[0~15]=129~144。
GPIO_DIR_OUTPUT定义GPIO的方向为输出,可以在include目录下gpio.h查看定义输出输入的标志,如下图所示。
图 34
- 配置GPIO的数据寄存器。
本案例中使用StarterWare的库函数GPIOPinWrite()来设置GPIO的值,例如:GPIOPinWrite(SOC_GPIO_0_REGS, 1, GPIO_PIN_HIGH)。
GPIOPinWrite()可以在include目录下gpio.h头文件查看定义,如下图所示。
图 35
SOC_GPIO_0_REGS是GPIO的基地址,第二个参数“1”是GPIO0[0]的编号。
GPIO的输出值通过GPIO_PIN_HIGH(高电平)和GPIO_PIN_LOW(低电平)来指定,可以在include目录下gpio.h头文件查看定义,如下图所示。
图 36
编译和运行LED控制程序
右击工程,在弹出来的对话框中点击“Build Project”,即可对当前工程编译,如下图所示。
图 37
编译完毕后,可在左侧工程的Binaries下看到生成的可执行led.out文件,如下图所示。
图 38
点击左上角的
load键,选择要加载的led.out文件,如下图所示。
图 39
等待程序加载完成,然后点击
程序运行按钮,可以发现评估底板的LED进行流水灯演示。按F5会进去函数里面,按F6单步运行代码。
按键中断裸机程序演示和解析
本小结将讲解如何利用现成的裸机程序,使用中断方式测试评估底板的按键,并详细解析此按键中断程序。
产品资料中提供按键中断程序镜像和源码,路径为:
GPIO_KEY.out:demoStarterWareBinaryGPIO_KEY.out //DSP镜像
main.c:demoStarterWareApplicationGPIO_KEYmain.c //DSP程序源码
导入工程
在工程导入前,请先使用GEL文件唤醒DSP核,也可参考产品资料用户手册中的《TMS320C6748开发案例使用手册》。然后点击CCS菜单“File -> Import”,弹出如下对话框。
图 40
点击“Code Composer Studio->Existing CCS Eclipse Projects”后,再点击Next,如下图所示。
图 41
在弹出的对话框的“Select search-directory”后面点击“Browse…”选择button的CCS工程的存放路径,选择后如下图所示。
图 42
点击Finish就可以导入现有CCS工程。然后右击工程,在弹出来的对话框中点击“Rebuild Project”,即可对当前工程编译,如下图所示。
图 43
编译完毕后,可在左侧工程的Binaries下看到生成的可执行button.out文件,如下图所示。
图 44
点击左上角的
load键,选择要加载的button.out文件,如下图所示。
图 45
等待程序加载完成,然后点击
程序运行按钮,再按下SW5和SW6按键,可以发现CCS的Console窗口有按键被按下的信息提示,如下图所示。
图 46
源代码解析
以下为按键中断函数的解析。
/****************************************************************************/
/* */
/* 按键中断测试 */
/* */
/* 2014年4月20日 */
/* */
/****************************************************************************/
#include "TL6748.h" // 创龙 DSP6748 开发板相关声明
#include "hw_types.h" // 宏命令
#include "hw_syscfg0_C6748.h" // 系统配置模块寄存器
#include "soc_C6748.h" // DSP C6748 外设寄存器
#include "psc.h" // 电源与睡眠控制宏及设备抽象层函数声明
#include "gpio.h" // 通用输入输出口宏及设备抽象层函数声明
#include "interrupt.h" // DSP C6748 中断相关应用程序接口函数声明及系统事件号定义
/****************************************************************************/
/* */
/* 宏定义 */
/* */
/****************************************************************************/
// 软件断点
#define SW_BREAKPOINT asm(" SWBP 0 ");
/****************************************************************************/
/* */
/* 全局变量 */
/* */
/****************************************************************************/
unsigned char Flag=0;
/****************************************************************************/
/* */
/* 函数声明 */
/* */
/****************************************************************************/
// 外设使能配置
void PSCInit(void);
// GPIO 管脚复用配置
void GPIOBankPinMuxSet();
// GPIO 管脚初始化
void GPIOBankPinInit();
// GPIO 管脚中断初始化
void GPIOBankPinInterruptInit(void);
// DSP 中断初始化
void InterruptInit(void);
// 中断服务函数
void USER0KEYIsr(void);
void USER1KEYIsr(void);
/****************************************************************************/
/* */
/* 主函数 */
/* */
/****************************************************************************/
int main(void)
{
// 外设使能配置
PSCInit();
// GPIO 管脚复用配置
GPIOBankPinMuxSet();
// GPIO 管脚初始化
GPIOBankPinInit();
// DSP 中断初始化
InterruptInit();
// GPIO 管脚中断初始化
GPIOBankPinInterruptInit();
unsigned int i;
// 主循环
for(;;)
{
// 亦可以使用查询法查询中断状态
if(Flag)
{
// 核心板 LED
for(i=0x00FFFFFF;i>0;i--); // 延时
GPIOPinWrite(SOC_GPIO_0_REGS, 109, GPIO_PIN_LOW);
GPIOPinWrite(SOC_GPIO_0_REGS, 110, GPIO_PIN_HIGH);
for(i=0x00FFFFFF;i>0;i--); // 延时
GPIOPinWrite(SOC_GPIO_0_REGS, 109, GPIO_PIN_HIGH);
GPIOPinWrite(SOC_GPIO_0_REGS, 110, GPIO_PIN_LOW);
}
}
}
/****************************************************************************/
/* */
/* PSC 初始化 */
/* */
/****************************************************************************/
void PSCInit(void)
{
// 使能 GPIO 模块
// 对相应外设模块的使能也可以在 BootLoader 中完成
PSCModuleControl(SOC_PSC_1_REGS, HW_PSC_GPIO, PSC_POWERDOMAIN_ALWAYS_ON, PSC_MDCTL_NEXT_ENABLE);
}
/****************************************************************************/
/* */
/* GPIO 管脚复用配置 */
/* */
/****************************************************************************/
void GPIOBankPinMuxSet(void)
{
// 配置相应的 GPIO 口功能为普通输入输出口
// 核心板 LED
GPIOBank6Pin12PinMuxSetup();
GPIOBank6Pin13PinMuxSetup();
// 底板按键
GPIOBank0Pin6PinMuxSetup();
GPIOBank6Pin1PinMuxSetup();
}
/****************************************************************************/
/* */
/* GPIO 管脚初始化 */
/* */
/****************************************************************************/
void GPIOBankPinInit(void)
{
// 配置 LED 对应管脚为输出管脚
// OMAPL138 及 DSP C6748 共有 144 个 GPIO
// 以下为各组 GPIO BANK 起始管脚对应值
// 范围 1-144
// GPIO0[0] 1
// GPIO1[0] 17
// GPIO2[0] 33
// GPIO3[0] 49
// GPIO4[0] 65
// GPIO5[0] 81
// GPIO6[0] 97
// GPIO7[0] 113
// GPIO8[0] 129
// 核心板 LED
GPIODirModeSet(SOC_GPIO_0_REGS, 109, GPIO_DIR_OUTPUT); // GPIO6[12]
GPIODirModeSet(SOC_GPIO_0_REGS, 110, GPIO_DIR_OUTPUT); // GPIO6[13]
// 底板按键
GPIODirModeSet(SOC_GPIO_0_REGS, 7, GPIO_DIR_INPUT); // USER0 KEY GPIO0[6]
GPIODirModeSet(SOC_GPIO_0_REGS, 98, GPIO_DIR_INPUT); // USER1 KEY GPIO6[1]
}
/****************************************************************************/
/* */
/* GPIO 管脚中断初始化 */
/* */
/****************************************************************************/
void GPIOBankPinInterruptInit(void)
{
// 底板按键中断
// 配置 USER0 KEY GPIO0[6] 为下降沿触发
GPIOIntTypeSet(SOC_GPIO_0_REGS, 7, GPIO_INT_TYPE_FALLEDGE);
// 配置 USER1 KEY GPIO6[1] 为上升沿及下降沿触发
GPIOIntTypeSet(SOC_GPIO_0_REGS, 98, GPIO_INT_TYPE_BOTHEDGE);
// 使能 GPIO BANK 中断
GPIOBankIntEnable(SOC_GPIO_0_REGS, 0); // USER0 KEY GPIO0
GPIOBankIntEnable(SOC_GPIO_0_REGS, 6); // USER1 KEY GPIO6
// 注册中断服务函数
IntRegister(C674X_MASK_INT4, USER0KEYIsr);
IntRegister(C674X_MASK_INT5, USER1KEYIsr);
// 映射中断到 DSP 可屏蔽中断
IntEventMap(C674X_MASK_INT4, SYS_INT_GPIO_B0INT);
IntEventMap(C674X_MASK_INT5, SYS_INT_GPIO_B6INT);
// 使能 DSP 可屏蔽中断
IntEnable(C674X_MASK_INT4);
IntEnable(C674X_MASK_INT5);
}
/****************************************************************************/
/* */
/* DSP 中断初始化 */
/* */
/****************************************************************************/
void InterruptInit(void)
{
// 初始化 DSP 中断控制器
IntDSPINTCInit();
// 使能 DSP 全局中断
IntGlobalEnable();
}
/****************************************************************************/
/* */
/* 中断服务函数 */
/* */
/****************************************************************************/
void USER0KEYIsr(void)
{
// 软件断点 方便调试
//SW_BREAKPOINT;
// 禁用 GPIO BANK 0 中断
GPIOBankIntDisable(SOC_GPIO_0_REGS, 0);
// 清除 GPIO BANK 0 中断状态
IntEventClear(SYS_INT_GPIO_B0INT);
if(GPIOPinIntStatus(SOC_GPIO_0_REGS, 7) == GPIO_INT_PEND)
{
// 清除 GPIO0[6] 中断状态
GPIOPinIntClear(SOC_GPIO_0_REGS, 7);
Flag=0;
}
// 使能 GPIO BANK 0 中断
GPIOBankIntEnable(SOC_GPIO_0_REGS, 0);
}
void USER1KEYIsr(void)
{
// 软件断点 方便调试
//SW_BREAKPOINT;
// 禁用 GPIO BANK 6 中断
GPIOBankIntDisable(SOC_GPIO_0_REGS, 6);
// 清除 GPIO BANK 6 中断状态
IntEventClear(SYS_INT_GPIO_B6INT);
if(GPIOPinIntStatus(SOC_GPIO_0_REGS, 98) == GPIO_INT_PEND)
{
// 清除 GPIO6[1] 中断状态
GPIOPinIntClear(SOC_GPIO_0_REGS, 98);
Flag=1;
}
// 使能 GPIO BANK 6 中断
GPIOBankIntEnable(SOC_GPIO_0_REGS, 6);
}
以上是按键中断程序注释,对于按键中断,操作步骤如下。
- 查看评估底板的原理图,找到与用户按键连接的GPIO编号。
评估底板与用户按键连接的GPIO分别是GPIO0[6]、GPIO6[1],如下图所示。
图 47
首先对处理器的PSC控制进行初始化,使用StarterWare的psc.h头文件提供的PSCModuleControl()来进行控制,因为PSC控制器涉及到较多的内容,这里仅对GPIO_KEY这个案例的用法含义做说明,详细信息请自行查看TMS320C6748的数据手册和技术参考手册。
向PSCModuleControl()传入GPIO的PSC寄存器地址,即SOC_PSC_1_REGS,基于HW_PSC_GPIO这个值做一个偏移到实际GPIO的PSC控制位,PSC_POWERDOMAIN_ALWAYS_ON和PSC_MDCTL_NEXT_ENABLE都是使能PSC相关的控制位,如下图所示。
图 48
查看TMS320C6748的数据手册,查找GPIO_LED对应的管脚的PINMUX寄存器的地址,将对应的管脚的寄存器中相应位设置为GPIO的工作模式。
为方便用户开发,我们已将GPIO复用等等配置操作直接封装成函数,用户如需使用,可以直接包含"TL6748.h"文件,并将产品资料"DemoStarterWareApplicationPlatform"目录下的源码复制到用户当前工程文件夹内即可。这里GPIO复用配置的函数是GPIOBankXPinXPinMuxSetup(),如下图所示。
图 49
本案例中使用StarterWare的库函数HWREG(x)来设置PINMUX的寄存器地址值,例如:HWREG(SOC_SYSCFG_0_REGS SYSCFG0_PINMUX(1))。
HWREG(x)可以在"includehw"目录下hw_types.h头文件查看定义,如下图所示。
图 50
SOC_SYSCFG_0_REGS是PINMUX的基地址,可以在"includehw"目录下soc_C6748.h头文件查看定义,如下图所示。
图 51
可以看出SOC_SYSCFG_0_REGS的值为0x01C14000,类似的地址值都可以在《TMS320C6748 Fixed- and Floating-Point DSP datasheet (Rev. G)》数据手册查到数据,下图为数据手册中SYSCFG0寄存器基址、结束地址、长度等信息。
图 52
图 53
SYSCFG0_PINMUX(1)是PINMUX1的偏移地址,可以在"include/hw"目录下hw_syscfg0_C6748.h头文件查看定义,如下图所示。
图 54
可以算出PINMUX1的偏移地址为0x124,那么可以算出PINMUX1的值为:PINMUX1=(0x01C14000 0x124)=0x01C14124。
具体的地址可以在产品资料“Datasheet核心板元器件CPU”目录下《TMS320C6748 DSP (Rev. C)》技术参考手册中找到,下图为技术参考手册中PINMUX1的值。
图 55
图 56
设置GPIO复用模式,根据数据手册"10.5.10.2 Pin Multiplexing Control 1 Register (PINMUX1)"章节PINMUX1寄存器的控制位说明,给其写入0x00000080即可配置为GPIO模式。
图 57
图 58
图 59
设置GPIO的方向为输入。
本案例中使用StarterWare的库函数GPIODirModeSet()将GPIO口配置为输出,例如:GPIODirModeSet(SOC_GPIO_0_REGS, 7, GPIO_DIR_INPUT)。
GPIODirModeSet()可以在include目录下gpio.h头文件查看声明,如下图所示。
图 60
SOC_GPIO_0_REGS是GPIO的基地址,可以在"includehw"目录下soc_C6748.h头文件查看定义,如下图所示。
图 61
可以看出SOC_GPIO_0_REGS的值为0x01E26000,类似的地址都可以在TMS320C6748 Fixed- and Floating-Point DSP datasheet (Rev. G)》数据手册找到,下图为数据手册查到的GPIO基地址的值。
图 62
图 63
第二个参数“1”是GPIO0[0]的编号,以下为各组GPIO第一个管脚的对应值(范围1~144):GPIO0[0~15]=1~16,GPIO1[0~15]=17~32,GPIO2[0~15]=33~48,GPIO3[0~15]=49~64,GPIO4[0~15]=65~80,GPIO5[0~15]=81~96,GPIO6[0~15]=97~112,GPIO7[0~15]=113~128,GPIO8[0~15]=129~144。
GPIO_DIR_INPUT定义GPIO的方向为输入,可以在include目录下egpio.h头文件查看定义输出输入的标志。在技术参考手册可查看GPIO的控制寄存器说明。如下图所示。
图 64
图 65
图 66
设置GPIO中断,这里需要设置GPIO的中断类型以及使能GPIO中断。gpio.h头文件已声明GPIO中断类型设置和使能的函数,在技术参考手册可以查看下降沿触发中断的设置方式和使能中断设置方法。
图 67
图 68
图 69
图 70
图 71
- 设置DSP中断控制器。
设置DSP中断控制器主要作用是初始化DSP中断控制器和使能全局中断,函数是StarterWare方便用户使用而提供的,用户只需要包含了相关头文件直接调用即可。
- 中断初始化,使用IntDSPINTCInit()函数;
- 使能全部中断,使用IntGlobalEnable()函数;
图 72
- 配置按键中断。
按键中断初始化函数中有以下几个作用:
- 注册按键中断服务函数,添加中断到中断向量列表。使用IntRegister()函数;
- 映射按键中断对应CPU中断,进入中断后程序会自动跳转到相应入口地址。使用IntEventMap();
- 使能按键对应的CPU中断,使用IntEnable();
- 调用中断服务函数,打印按键被按下的信息,使用USERXKEYIsr();
图 73
图 74
图 75
- 调试仿真。
进入仿真后运行程序,按下按键可以看到CCS的Console窗口有打印相对应的按键信息。
图 76
到这里已经介绍完所有的基本GPIO操作的过程及机制,用户可以自行参照这个过程去分析其他案例的具体操作过程。