主要功能:
(1)利用定时器timer0设置每10ms进入一次的中断模式;在此基础上让LD3灯以1秒的频率亮灭(0.5秒亮0.5秒灭依次循环下去)和蜂鸣器以5秒的频率响一秒钟。
(2) 利用定时器timer0设置每10ms进入一次的中断模式,在此基础上让LD3灯以1秒的频率亮灭(0.5秒亮0.5秒灭依次循环下去);利用定时器timer1设置每1000ms进入一次的中断模式,让蜂鸣器以5秒的频率响一秒钟。
报告:
一、实验目的及要求 熟悉 TMS320F28335 的 GPIO 配置过程; 学会用 GPIO 控制 Led、蜂鸣器等简单功能,并深入学习 F28335 的 GPIO 模块; |
二、实验原理与内容 1、实验原理 通过定时器定时控制Led灯和数码管。第一次实验可以先不用关心定时器功能。把重点放在GPIO功能上,后期会介绍定时器功能; 在SXD28335_SYS_PRO_I的开发板中,DSP的GPIO0/EPWM1A管脚有两个功能:GPIO(普通输入输出IO口功能)和PWM功能。这里配置为GPIO功能。 GPIO53/EQEP1I/XD26 管脚有三个功能:GPIO(普通输入输出IO口功能)、EQEP1I 功能和数据总线功能,这里配置为GPIO功能。 GPIO0/EPWM1A管脚通过插针J19(实验时需要用跳线帽将其短路)与LD3(LED灯)链接。GPIO0/EPWM1A 管脚链接到了LD3的阴极,如果想让灯亮则需要控制GPIO0/EPWM1A管脚为输出并且是低电平。如果想让灯灭则需要控制 GPIO0/EPWM1A 管脚为输出并且是高电平;  图 1 LED 灯的硬件连接图 GPIO53管脚通过插针J15与三级管链接控制蜂鸣器。如果想让蜂鸣器响则需要控制GPIO53 管脚为输出并且是低电平(三极管的集电极和发射极导通有电流功能蜂鸣器)。否则需要控制GPIO53管脚为输出并且是高电平;  图 2 蜂鸣器的硬件连接图 2、实验内容(要求) (1)利用定时器timer0设置每10ms进入一次的中断模式;在此基础上让LD3灯以1秒的频率亮灭(0.5秒亮0.5秒灭依次循环下去)和蜂鸣器以5秒的频率响一秒钟。  图 3 问题1流程图 (2) 利用定时器timer0设置每10ms进入一次的中断模式,在此基础上让LD3灯以1秒的频率亮灭(0.5秒亮0.5秒灭依次循环下去);利用定时器timer1设置每1000ms进入一次的中断模式,让蜂鸣器以5秒的频率响一秒钟。  图 4 问题2流程图 |
三、实验软硬件环境 1、计算机(已安装CCSv6.1.3开发环境) 2、SXD28335_SYS_PRO_III 开发板 3、5V 2A(或3A)DC电源 4、仿真器(XDS100v2仿真器一套) |
四、实验过程(实验步骤、记录、数据、分析) 1. 连接实验设备; ² 连接仿真器和开发板 插入外部+5V 电源 2. 打开CCSv6.1.3;  图 5 CCS 工程目录 3. 点击菜单 Project->Import CCS Projects...;点击 browse;选择 D:\ti\workspace\Example_2833x_LEDBlink,点击确定;  图 6 CCS 导入工程方法 4. 连接仿真器与设备并上电; 5. 进行仿真器配置,由于CCS支持很多处理器和仿真器,它不知道用户目前用的是哪个仿真器和DSP,所以要通过配置文件告诉 CCS 软件。在此详细讲解下仿真器的配置步骤。这里以XDS100V2为例,其余仿真器型号配置与此类似: (1)File->New Target Configuration File,设置 File Name:XDS100V2_F28335.ccxml (2)Use Share Location:复选,点 Finish。  图 7 配置文件的命名  图 8 配置文件的设置 进行如上设置,点击右侧的 Save,其变为灰色后,点击高亮的 Test Connect,在弹出的 TXT 文件的最后一行为:The JTAG DR Integrity scan-test has succeeded.,则说明仿真器正 常连接目标板;  图 9 测试链接成功 6. 在 CCS6.1.3 的菜单栏 View->Target Configuration,在 Target Configuration 栏下有 User Defined,选择 XDS100V3_28335,右键点击 Set As Default,自此我们建立了一 个针对 28335 的配置,以后不需要每个工程都进行此配置;  图 10 设置为默认的配置文件 7. 在线调试工程,载入调试界面;  图 11 调试工程 |
五、测试/调试及实验结果分析 实验结果: 实验现象观察,Led灯闪烁,每几秒蜂鸣器发出短暂(1秒左右)的蜂鸣声; GPIO 外设简介: 图 12为 GPIO0~GPIO27 模块的内部功能图。由于 28335 的大部分 IO 口都有复用功能,也就是GPIO口只是它的一个普通功能,有的IO口还有PWM 功能、SCI功能和SPI功能等。这里首先关注GPIO功能;  图 12 GPIO 功能外设 这里涉及到几个要用到的寄存器: 1、功能选择寄存器 GPAMUX1/2;每组IO一般有32个IO口可以配置。GPAMUX1对应每组的低16个IO口,GPAMUX2对应高16个IO口。  图 13 GPAMUX 配置 2、方向控制寄存器GPADIR:如果对应的位为1则配置为输出,否则则配置为输入。 3、置位寄存器 GPASET:如果对应的位为1则将对应的IO口拉高(输出高电平)。 4、强制拉低管脚 GPACLEAR:如果对应的位为1则将对应的IO口拉低(输出低电平)。 5、输出状态翻转寄存器GPATOGGLE:如果GPATOGGLE的某位为1则将相应的IO口输出状态进行翻转。 6、通用输入输出数据寄存器GPBDAT:如果 GPBDAT的某位为1则将相应的IO口输出高电平状态,否则输出低电平状态。 程序解析: 实验内容(1)的程序: // ###########################################################################
//
// FILE: Example_2833xLedBlink.c
//
// TITLE: DSP2833x eZdsp LED Blink Getting Started Program.
//
// ASSUMPTIONS:
//
// 这个程序需要DSP2833x头文件。.
//
//
// 如所提供的,这个项目被配置为“引导到SARAM”。
// 操作。2833x启动模式表如下所示。
// 有关配置eZdsp启动方式的信息,
// 请参考eZdsp附带的文档,
//
// $Boot_Table:
//
// GPIO87 GPIO86 GPIO85 GPIO84
// XA15 XA14 XA13 XA12
// PU PU PU PU
// ==========================================
// 1 1 1 1 Jump to Flash
// 1 1 1 0 SCI-A boot
// 1 1 0 1 SPI-A boot
// 1 1 0 0 I2C-A boot
// 1 0 1 1 eCAN-A boot
// 1 0 1 0 McBSP-A boot
// 1 0 0 1 Jump to XINTF x16
// 1 0 0 0 Jump to XINTF x32
// 0 1 1 1 Jump to OTP
// 0 1 1 0 Parallel GPIO I/O boot
// 0 1 0 1 Parallel XINTF boot
// 0 1 0 0 Jump to SARAM <- "boot to SARAM"
// 0 0 1 1 Branch to check boot mode
// 0 0 1 0 Boot to flash, bypass ADC cal
// 0 0 0 1 Boot to SARAM, bypass ADC cal
// 0 0 0 0 Boot to SCI-A, bypass ADC cal
// Boot_Table_End$
//
// DESCRIPTION:
//
// This example configures CPU Timer0 for a 500 msec period, and toggles the GPIO32
// LED on the 2833x eZdsp once per interrupt. For testing purposes, this example
// also increments a counter each time the timer asserts an interrupt.
//
// Watch Variables:
// CpuTimer0.InterruptCount
//
// Monitor the GPIO32 LED blink on (for 500 msec) and off (for 500 msec) on the 2833x eZdsp.
//
// ###########################################################################
#include "DSP28x_Project.h" // 设备头文件和示例包括文件
Uint16 Timer_10ms_flag;
Uint16 Timer_100ms_flag;
Uint16 Buzzer_flag;
Uint16 Timer_100ms_Count;
Uint32 Timer_1000ms_Count;
Uint32 Timer_5000ms_Count;
// 为了Buzzer_On1000ms()函数的可移植性,使用了宏定义。
// 蜂鸣器的接通与断开要参考实际驱动电路硬件,本次使用蜂鸣器驱动电路是低电平接通并工作
#define Buzzer_Pin_On GpioDataRegs.GPBDAT.bit.GPIO53 = 0 //打开蜂鸣器
#define Buzzer_Pin_Off GpioDataRegs.GPBDAT.bit.GPIO53 = 1 //关闭蜂鸣器
// 宏定义
// 蜂鸣器响一秒钟触发条件
#define Buzzer_On1000ms_Trigger Buzzer_flag = 1 //蜂鸣器响一秒钟触发条件
// 函数初始化
void GPIO_Init(void);
void Buzzer_On1000ms(void);
// 在此文件中找到的函数的原型语句.
interrupt void cpu_timer0_isr(void);
//定时器 0 中断函数
void main(void)
{
// 步骤1. 初始化系统控制:
InitSysCtrl();
//变量初始化
Timer_10ms_flag = 0;
Timer_100ms_flag = 0;
Timer_100ms_Count = 0;
Timer_1000ms_Count = 0;
Timer_5000ms_Count = 0;
Buzzer_flag = 0;
// 步骤2 初始化 GPIO:
GPIO_Init();
// 步骤3。清除所有中断并初始化PIE向量表:
// 禁用CPU中断
DINT;
// 将PIE控制寄存器初始化为其默认状态。
InitPieCtrl();
// 禁用CPU中断并清除所有CPU中断标志:
IER = 0x0000;
IFR = 0x0000;
// 用指向shell Interrupt的指针初始化PIE向量表
InitPieVectTable();
EALLOW;
// 这是写入EALLOW保护寄存器所必需的
PieVectTable.TINT0 = &cpu_timer0_isr;
EDIS;
// 这需要禁用对EALLOW保护寄存器的写操作
// 步骤4。初始化设备外设.
InitCpuTimers();
// 初始化Cpu计时器
#if (CPU_FRQ_150MHZ) // 此次编译150MHz
// 配置CPU-Timer 0每10毫秒中断一次:
// 150MHz CPU频率,10毫秒周期(单位:秒)
ConfigCpuTimer(&CpuTimer0, 150, 10000);
#endif
#if (CPU_FRQ_100MHZ)
// 配置CPU-Timer 0每500毫秒中断一次:
// 100MHz CPU频率,500毫秒周期(单位:秒)
ConfigCpuTimer(&CpuTimer0, 100, 500000);
#endif
// 下面的设置也必须更新
CpuTimer0Regs.TCR.all = 0x4001;
// 使用只写指令设置TSS= 0
// 第5步.用户特定代码,启用中断:
// 配置GPIO32为GPIO输出引脚
// 使能连接CPU- timer 0的CPU INT1
IER |= M_INT1;
// 使能PIE: Group 1中断7中的TINT0
PieCtrlRegs.PIEIER1.bit.INTx7 = 1;
// 启用全局中断和更高优先级的实时调试事件:
EINT;
// 启用全局中断INTM
ERTM;
// 启用全局实时中断DBGM
// 步骤6.无限循环执行里面的程序:
while (1)
{
if (Timer_10ms_flag) //10ms进去执行一次
{
Timer_10ms_flag = 0;
if (++Timer_100ms_Count >= 10)
{
Timer_100ms_Count = 0;
Timer_100ms_flag = 1;
}
}
if (Timer_100ms_flag) //100ms进去执行一次
{
Timer_100ms_flag = 0;
Buzzer_On1000ms();
}
if (Timer_1000ms_Count >= 50) //500ms进去执行一次
{
Timer_1000ms_Count = 0;
GpioDataRegs.GPATOGGLE.bit.GPIO0 = 1;
//LED
}
if (Timer_5000ms_Count >= 500) //5000ms进去执行一次
{
Timer_5000ms_Count = 0;
//Buzzer_flag=1;
Buzzer_On1000ms_Trigger;
}
}
}
// 定时器0中断函数
interrupt void cpu_timer0_isr(void)
{
CpuTimer0.InterruptCount++;
Timer_10ms_flag = 1;
Timer_1000ms_Count++;
Timer_5000ms_Count++;
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
}
/**
* 函数名:void GPIO_Init()
*@brief GPIO初始化
*设置GPIO上电默认状态
*/
void GPIO_Init()
{
EALLOW;
// 用于蜂鸣器驱动
GpioCtrlRegs.GPBMUX2.bit.GPIO53 = 0;
GpioCtrlRegs.GPBDIR.bit.GPIO53 = 1;
// 用于LED灯驱动
GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 0;
GpioCtrlRegs.GPADIR.bit.GPIO0 = 1;
EDIS;
//设置默认上电GPIO口的状态
GpioDataRegs.GPADAT.bit.GPIO0 = 1;
//LED
GpioDataRegs.GPBDAT.bit.GPIO53 = 1;
//buzzer
}
// void Buzzer_On1000ms()改进前
/**
* 函数名:void Buzzer_On1000ms()
*@brief 驱动蜂鸣器工作一秒钟
*Buzzer_flag=1时蜂鸣器才触而发工作
*此函数要放在100ms时间片扫描执行
*/
/*
void Buzzer_On1000ms()
{
static Uint16 Flag;
//Flag=1:蜂鸣器已经打开;Flag=0:蜂鸣器未打开
static Uint16 Timer_Count;
if (Flag == 1)
{
if (++Timer_Count >= 10)
{
Timer_Count = 0;
Buzzer_flag = 0;
}
else
{
return;
}
}
if (Buzzer_flag == 1)
{
Flag = 1;
GpioDataRegs.GPBDAT.bit.GPIO53 = 0;
}
else
{
if (Flag == 0)
return;
//直接退出,目的是在此函数不开启蜂鸣器驱动时把GPIO53控制权限释放出来,否则GPIO53一直被设置高电平
GpioDataRegs.GPBDAT.bit.GPIO53 = 1;
Flag = 0;
}
}*/
// void Buzzer_On1000ms()改进后
/**
* 函数名:void Buzzer_On1000ms()
*@brief 驱动蜂鸣器工作一秒钟
*Buzzer_flag=1时蜂鸣器才触而发工作
*此函数要放在100ms时间片扫描执行
*/
void Buzzer_On1000ms()
{
static Uint16 Flag;
//Flag=1:蜂鸣器已经打开;Flag=0:蜂鸣器未打开
static Uint16 Timer_Count;
if (Flag == 1)
{
if (++Timer_Count >= 10)
//必要时可以修改蜂鸣器的工作时长,但是最短时间为100ms
{
Timer_Count = 0;
Buzzer_flag = 0;
}
else
{
return;
}
}
if (Buzzer_flag == 1)
{
Flag = 1;
Buzzer_Pin_On;
}
else
{
if (Flag == 0)
return;
//直接退出,目的是在此函数不开启蜂鸣器驱动时把GPIO53控制权限释放出来,否则GPIO53一直被设置高电平
Buzzer_Pin_Off;
Flag = 0;
}
}
//=========================================================================
// No more.
//========================================================================= 实验内容(2)的程序: #include "DSP28x_Project.h" // 设备头文件和示例包括文件
Uint16 Timer_10ms_flag;
Uint16 Timer_100ms_flag;
Uint16 Buzzer_flag;
Uint16 Timer_100ms_Count;
Uint32 Timer_1000ms_Count;
Uint32 Timer_5000ms_Count;
// 为了Buzzer_On1000ms()函数的可移植性,使用了宏定义。
// 蜂鸣器的接通与断开要参考实际驱动电路硬件,本次使用蜂鸣器驱动电路是低电平接通并工作
#define Buzzer_Pin_On GpioDataRegs.GPBDAT.bit.GPIO53 = 0 //打开蜂鸣器
#define Buzzer_Pin_Off GpioDataRegs.GPBDAT.bit.GPIO53 = 1 //关闭蜂鸣器
// 蜂鸣器响一秒钟触发条件
#define Buzzer_On1000ms_Trigger Buzzer_flag = 1 //蜂鸣器响一秒钟触发条件
// 函数初始化
void GPIO_Init(void);
void Buzzer_On1000ms(void);
// Prototype statements for functions found within this file.
__interrupt void cpu_timer0_isr(void);
__interrupt void cpu_timer1_isr(void);
__interrupt void cpu_timer2_isr(void);
void main(void)
{
// 步骤1. 初始化系统控制:
InitSysCtrl();
//变量初始化
Timer_10ms_flag = 0;
Timer_100ms_flag = 0;
Timer_100ms_Count = 0;
Timer_1000ms_Count = 0;
Timer_5000ms_Count = 0;
Buzzer_flag = 0;
// 步骤2 初始化 GPIO:
GPIO_Init();
// 步骤3。清除所有中断并初始化PIE向量表:
// 禁用CPU中断
DINT;
// 将PIE控制寄存器初始化为其默认状态。
InitPieCtrl();
// 禁用CPU中断并清除所有CPU中断标志:
IER = 0x0000;
IFR = 0x0000;
// 用指向shell Interrupt的指针初始化PIE向量表
InitPieVectTable();
EALLOW;
// 这是写入EALLOW保护寄存器所必需的
PieVectTable.TINT0 = &cpu_timer0_isr;
PieVectTable.XINT13 = &cpu_timer1_isr;
PieVectTable.TINT2 = &cpu_timer2_isr;
EDIS;
// 这需要禁用对EALLOW保护寄存器的写操作
// 步骤4。初始化设备外设.
InitCpuTimers();
// 初始化Cpu计时器
#if (CPU_FRQ_150MHZ) // 此次编译150MHz
// 配置CPU-Timer 0每10毫秒中断一次:
// 150MHz CPU频率,10毫秒周期(单位:秒)
// 配置CPU-Timer 1每1000毫秒中断一次:
// 150MHz CPU频率,1000毫秒周期(单位:秒)
ConfigCpuTimer(&CpuTimer0, 150, 10000);
ConfigCpuTimer(&CpuTimer1, 150, 1000000);
ConfigCpuTimer(&CpuTimer2, 150, 1000000);
#endif
#if (CPU_FRQ_100MHZ)
// 配置CPU-Timer 0每500毫秒中断一次:
// 100MHz CPU频率,500毫秒周期(单位:秒)
ConfigCpuTimer(&CpuTimer0, 100, 10000);
ConfigCpuTimer(&CpuTimer1, 100, 1000000);
ConfigCpuTimer(&CpuTimer2, 100, 1000000);
#endif
// 下面的设置也必须更新
CpuTimer0Regs.TCR.all = 0x4001;
// 使用只写指令设置TSS= 0
// 第5步.用户特定代码,启用中断:
// 配置GPIO32为GPIO输出引脚
CpuTimer0Regs.TCR.all = 0x4000;
// 使用只写指令设置 TSS 位 = 0
CpuTimer1Regs.TCR.all = 0x4000;
// 使用只写指令设置 TSS 位 = 0
CpuTimer2Regs.TCR.all = 0x4000;
// 使用只写指令设置 TSS 位 = 0
// 使能连接CPU- timer 0的CPU INT1
IER |= M_INT1;
IER |= M_INT13;
IER |= M_INT14;
// 使能PIE: Group 1中断7中的TINT0
PieCtrlRegs.PIEIER1.bit.INTx7 = 1;
// 启用全局中断和更高优先级的实时调试事件:
EINT;
// 启用全局中断INTM
ERTM;
// 启用全局实时中断DBGM
// 步骤6.无限循环执行里面的程序:
while (1)
{
if (Timer_10ms_flag) //10ms进去执行一次
{
Timer_10ms_flag = 0;
if (++Timer_100ms_Count >= 10)
{
Timer_100ms_Count = 0;
Timer_100ms_flag = 1;
}
}
if (Timer_100ms_flag) //100ms进去执行一次
{
Timer_100ms_flag = 0;
Buzzer_On1000ms();
}
if (Timer_1000ms_Count >= 50) //500ms进去执行一次
{
Timer_1000ms_Count = 0;
GpioDataRegs.GPATOGGLE.bit.GPIO0 = 1;
//LED
}
if (Timer_5000ms_Count >= 5) //5000ms进去执行一次
{
Timer_5000ms_Count = 0;
//Buzzer_flag=1;
Buzzer_On1000ms_Trigger;
}
}
}
__interrupt void cpu_timer0_isr(void)
{
CpuTimer0.InterruptCount++;
Timer_10ms_flag = 1;
Timer_1000ms_Count++;
// 确认此中断以接收来自组1的更多中断
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
}
__interrupt void cpu_timer1_isr(void)
{
CpuTimer1.InterruptCount++;
Timer_5000ms_Count++;
// CPU确认中断
EDIS;
}
__interrupt void cpu_timer2_isr(void)
{
EALLOW;
CpuTimer2.InterruptCount++;
// CPU确认中断
EDIS;
}
/**
* 函数名:void GPIO_Init()
*@brief GPIO初始化
*设置GPIO上电默认状态
*/
void GPIO_Init()
{
EALLOW;
// 用于蜂鸣器驱动
GpioCtrlRegs.GPBMUX2.bit.GPIO53 = 0;
GpioCtrlRegs.GPBDIR.bit.GPIO53 = 1;
// 用于LED灯驱动
GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 0;
GpioCtrlRegs.GPADIR.bit.GPIO0 = 1;
EDIS;
//设置默认上电GPIO口的状态
GpioDataRegs.GPADAT.bit.GPIO0 = 1;
//LED
GpioDataRegs.GPBDAT.bit.GPIO53 = 1;
//buzzer
}
/**
* 函数名:void Buzzer_On1000ms()
*@brief 驱动蜂鸣器工作一秒钟
*Buzzer_flag=1时蜂鸣器才触而发工作
*此函数要放在100ms时间片扫描执行
*/
void Buzzer_On1000ms()
{
static Uint16 Flag;
//Flag=1:蜂鸣器已经打开;Flag=0:蜂鸣器未打开
static Uint16 Timer_Count;
if (Flag == 1)
{
if (++Timer_Count >= 10)
//必要时可以修改蜂鸣器的工作时长,但是最短时间为100ms
{
Timer_Count = 0;
Buzzer_flag = 0;
}
else
{
return;
}
}
if (Buzzer_flag == 1)
{
Flag = 1;
Buzzer_Pin_On;
}
else
{
if (Flag == 0)
return;
//直接退出,目的是在此函数不开启蜂鸣器驱动时把GPIO53控制权限释放出来,否则GPIO53一直被设置高电平
Buzzer_Pin_Off;
Flag = 0;
}
}
//=========================================================================
// No more.
//=========================================================================
|
六、实验结论 通过本次GPIO控制LED及蜂鸣器的实验,深入了解了GPIO的基本工作原理,并成功实现了通过GPIO控制LED灯的亮灭以及蜂鸣器的鸣响。掌握了定时器的配置方法,并学会了利用中断服务程序来实现对LED和蜂鸣器的控制。 实验结果表明,能够精确地控制LED灯以特定的频率进行亮灭切换,以及控制蜂鸣器以特定的频率和时长进行响铃。通过调整定时器的中断频率和中断服务程序中的逻辑,我能够灵活地改变LED和蜂鸣器的行为。 此外,在实验中也注意到了中断服务程序执行时间的重要性。为了避免影响系统的实时性,尽量简化了中断服务程序中的代码,并确保其执行时间尽可能短。这种设计思路对于保证嵌入式系统的稳定性和性能至关重要。 |
参考资料:
1、三兄弟嵌入式 ,网址: http://sxdembed.taobao.com
2、硬件:玻尔电子宙斯盾板之SXD28335B_QFP

注意:其它缺失文件请参考三兄弟嵌入式的玻尔电子宙斯盾板之SXD28335B_QFP软件例程,本次只是对主要功能的要求进行验证。