[调查/报告]DSP2812实验指导书
DSP在电力系统中的应用
实验指导书
电气工程实验中心
2009年6月
实验1 CPU Timer实验 3
一、CPU Timer实验 ....................................................................................................... 3
二、共享文件DSP281x_CpuTimers.c程序 ................................................................... 6
实验2 GPIO实验 .................................................................................................................. 10
一、GpioLoopback实验 ................................................................................................ 10
二、GpioToggle实验 ..................................................................................................... 21 实验3 SCI实验 ..................................................................................................................... 29
一、SCI Autobaud 实验 ................................................................................................ 29
二、Sci_FFDLoopBack实验 ......................................................................................... 37
三、Sci_LoopBack_Interrupts实验............................................................................... 41
实验4 SPI实验 ...................................................................................................................... 50
一、Spi数字回送实验 .................................................................................................. 50
二、Spi DAC实验 ......................................................................................................... 54 实验5 看门狗实验 ................................................................................................................ 60 实验6 事件管理器实验 ........................................................................................................ 64
一、EvPwm实验 ........................................................................................................... 64
二、事件管理器管理通用目的(GP)定时器示例程序 ................................................. 75
实验7 Xram实验................................................................................................................... 84 实验8 软件区分中断优先权实验 ........................................................................................ 88 实验9 外部扩展接口运行实验 .......................................................................................... 109 实验10 DAC实验 ............................................................................................................... 114 实验11 IIC 基本通信测试文件.......................................................................................... 118
附:Iic_Bottom.c程序 ................................................................................................. 123
实验1 CPU Timer实验
一、CPU Timer实验
文件: Example_281xCpuTimer.c
标题: DSP281x Device Getting Started Program. 说明: 该程序需DSP281x V1.00头文件支持,也可将其配置为"boot to H0"操作方式除了boot方式配置之
外,无其他可需的硬件配置方式
功能: (1) 本示例对CPU定时器0进行配置,定时器0每产生一次中断计数器加1,最大中断次数为
10进制9999。
(2) 在右边4个数码管上以10进制显示定时器中断的次数。在左边4个数码管上以16进制显
示定时器中断的次数。
(3) GPIO A端口控制的16个发光二极管随着中断闪烁。
观察变量: 可通过CCS视窗观察中断次数 CpuTimer0.InterruptCount ********************************************************************************************
#include "DSP281x_Device.h" // DSP281x 头文件包含文件
#include "DSP281x_Examples.h" // DSP281x 示例包含文件
// 由本文件建立的函数原型声明
interrupt void cpu_timer0_isr(); // CPU定时器0中断服务函数。
void LedD_Display(); // 在右边4个数码管上以10进制显示定时器中断的次数。 void LedH_Display(); // 在左边4个数码管上以16进制显示定时器中断的次数。 void delay(); // 延时函数
// 全局变量定义
int count=0; // count用于向 Bc7281.c 函数传递中断次数,以便在数码管上显示。
// 主函数
void main(void)
{
// 步骤1. 初始化系统控制:PLL, WatchDog,使能外设时钟
// InitSysCtrl()函数由DSP281x_SysCtrl文件建立
InitSysCtrl();
// 步骤2. 初始化GPIO。
// InitGpio()函数由DSP281x_Gpio.c文件建立,该文件阐明如何将GPIO
// 设置为默认状态。本范例跳过该函数
//InitGpio();
// 以下5条指令与中断程序中的 GpioDataRegs.GPATOGGLE.all = 0xFFFF;
// 指令构成A端口取反程序.
EALLOW; // 允许访问受保护的寄存器
GpioMuxRegs.GPAMUX.all=0; // 将A端口设置成IO方式
GpioMuxRegs.GPADIR.all=0xffff; // 将GPIO A所有15个端口配置成数字量输出
EDIS; // 禁止访问受保护的寄存器
GpioDataRegs.GPADAT.all=0x5555; // 间隔一个点亮LED发光二极管。
// 步骤3. 关闭所有中断并初始化PIE向量表:
// 关CPU中断
DINT; // 禁止可屏蔽中断。
// 将PIE控制寄存器初始化为默认状态,该状态关所有PIE中断并清除所有
// 标志。InitPieCtrl()函数由DSP281x_PieCtrl.c文件建立。
InitPieCtrl();
// 关CPU中断并清除所有CPU中断标志
IER = 0x0000;
IFR = 0x0000;
// 初始化PIE向量表,该向量表指明了中断服务程序(ISR)的一种构架。
// 即使在这个示例中用不到中断,仍板上组装了整个PIE向量表。作为调试
// 目的这是很有用的。ISR程序架构由DSP281x_DefaultIsr.c文件建立。
// InitPieVectTable()函数由DSP281x_PieVect.c文件建立。
InitPieVectTable();
// 本示例使用的中断重新映射到由本文件建立的ISR函数中。
EALLOW; // 允许访问受保护的寄存器 //******************************************************************************************
// 关于 "PieVectTable.TINT0 = &cpu_timer0_isr;" 指令的说明 // 1. cpu_timer0_isr 是一个CPU定时0中断服务程序(ISR)。
// 2. 这个中断程序与中断扩展(PIE)向量表第1组INT1第7个中断向量TINT0 // (CPU-定时器0)中断对应。
// 3. 为了使这个程序响应对应的中断,还需作如下配置:
//
// PieCtrlRegs.PIECRTL.bit.ENPIE = 1; // 使能PIE向量表。这条指令在在上面引用函数InitPieVectTable()中。 //
// IER |= M_INT1; // 使能PIE向量表第1组CPU INT1中断 // PieCtrlRegs.PIEIER1.bit.INTx7 = 1; // 使能 PIE 第1组 第7个即TINT0 // // (CPU-定时器0)中断 // 这几条指令在本程序的后续指令中可以找到。这样,在发生TINT0中断的情况下,将执行//cpu_timer0_isr()中断服务程序。
// "PieVectTable.TINT0 = &cpu_timer0_isr;" 指令实际上就是通知编译器,在发生TINT0中断的情况下,//将执行cpu_timer0_isr()中断服务程序。cpu_timer0_isr头上的"&"为取地址运算符。 //******************************************************************************************
PieVectTable.TINT0 = &cpu_timer0_isr;
EDIS; // 禁止访问受保护的寄存器
// 步骤4. 初始化器件所有外设。InitPeripherals()函数由DSP281x_InitPeripherals.c文件建立。
//InitPeripherals(); // 本示例跳过这个函数
// 定时器0初始化,由共享文件DSP281x_CpuTimers.c中的InitCpuTimers()
// 函数给出。用户不必作任何修改,可直接引用。
InitCpuTimers();
//******************************************************************************************
// ConfigCpuTimer()函数来自DSP281x_CpuTimers.c文件。在这个文件中已经对这个函数作了较为 // 详细的中文注释供参考。这里只作简单介绍。
// 定时器0设置是通过DSP281x_CpuTimers.c文件中的函数:
// ConfigCpuTimer(struct CPUTIMER_VARS *Timer, float Freq, float Period)完成的。该函数
// 有3个形参,第二第三形参分别是预置频率(float Freq)和周期(float Period),第一形参为 // struct CPUTIMER_VARS *Timer,它是一个具有CPUTIMER_VARS结构体类型的指针变量Timer。 // 因此,对它的赋值不象对第二第三形参那样赋给常数值,而是赋给一个地址。实际指令中的第一 // 个参数 &CpuTimer0 的含义为: 将CpuTimer0的地址赋给指针变量Timer。当然,如果需要,也可 // 将CpuTimer1或者CpuTimer2的地址赋给指针变量Timer。实际上,第一个参数是对定时器0/1/2作 // 出一个选择。之后,第二个和第三个参数放入由第一个参数选定的某定时器的对应寄存器中。 // 第二及第三实参的乘积决定延时的长短。 更详细的内容参考DSP281x_CpuTimers.c文件。 //******************************************************************************************
ConfigCpuTimer(&CpuTimer0, 100, 1000);
StartCpuTimer0();
// 步骤5. 应用代码,中断使能
// 使能连接 CPU-Timer 0 的INT1中断
IER |= M_INT1;
// 在DSP281x_Device.h文件中,已经定义 M_INT1=0x0001, P57
// IER为CPU中断使能寄存器,这条指令de含义为: 使能CPU INT1第一组中断。
// 这里用了按位或复合运算符"|=",其用意是不破坏IER原有结构。不能简单
// 地用 "IER = 0x0001;" 指令。如此,IER原有结构被破坏了。
// 使能PIE中的TINT0,1组第7个中断
PieCtrlRegs.PIEIER1.bit.INTx7 = 1; // P186
// PIE中断使能寄存器PIEIERx(x=1-12),高8位保留,低8位为:INTx.8-INTx.1
// 当INTx.y=1,使能中断服务;
// 当INTx.y=0,将使该位中断服务无效。
// INTx7=PIEIER1[6] = 1,使能 PIE 1组 第7个即 TINT0(CPU-定时器0)中断
// 使能全局中断,实时调试优先
EINT; // 使能INTM全局中断
ERTM; // 使能DBGM全局实时中断
//CpuTimer0.RegsAddr = &CpuTimer0Regs; // 取CpuTimer0Regs地址
// 空循环
for(;;);
}
/******************************************************************************************
函数: cpu_timer0_isr()
功能: CPU定时器0中断服务函数。每中断一次,中断计数器加1,并分别以10进制,16进制在右边
和左边4个数码管上进行显示。
******************************************************************************************/
interrupt void cpu_timer0_isr(void) {
if(CpuTimer0.InterruptCount>9999) CpuTimer0.InterruptCount=0;
CpuTimer0.InterruptCount++;
count=CpuTimer0.InterruptCount;
LedD_Display(); //在右边4个数码管上以10进制显示定时器中断的次数。
LedH_Display(); //在左边4个数码管上以16进制显示定时器中断的次数。
GpioDataRegs.GPATOGGLE.all = 0xffff; // A端口取反
// 应答这个中断以便从PIE 1组接收后面的中断
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; // PIEACK_GROUP1=0x0001 (见P185)
// PIE中断应答寄存器 PIEACKx,如果在组中断里有一个中断是未处理的,向各自
// 的中断位写1,使PIE块驱动一个脉冲进入核中断输入。
// PIEACK=PIEACK_GROUP1=0x0001,使PIE块驱动一个脉冲进入核INT1中断输入。 }
/*******************************************************************************************
函数名称: delay(Uint16 dly)
函数功能: 延时函数
输入参数: 形参dly,dly越大延时越久
输出参数: 无
*******************************************************************************************/
void delay(Uint16 dly)
{
Uint16 i;
for(;dly>0;dly--)
{
for(i=0;i<60000;i++);
}
}
//================================================================================
二、共享文件DSP281x_CpuTimers.c程序
文件: DSP281x_CpuTimers.c
标题: DSP281x CPU 32位定时器初始化及支持函数
注意: CPU定时器1及CPU定时器2保留用作DSP BIOS及其他实时操作系统如果你
要用DSP-BIOS
或者另外的实时操作系统,请不要在你的应用系统中使用这两个定时器。
由于这个原因,凡使用这两个定时器的代码都给出注释并在本范例不予使用。
********************************************************************************************
#include "DSP281x_Device.h" // DSP281x 头文件包含文件
#include "DSP281x_Examples.h" // DSP281x 示例包含文件
struct CPUTIMER_VARS CpuTimer0; // 定义CpuTimer0为具有CPUTIMER_VARS结构体类型的变量 // 定时器1及定时器2保留用作DSP BIOS及其它的实时操作系统
// struct CPUTIMER_VARS CpuTimer1; // 结构体定义
// struct CPUTIMER_VARS CpuTimer2;
/****************************************************************************
函数: InitCpuTimers()
功能: Cpu定时器初始化
****************************************************************************/
// InitCpuTimers()函数将3个CPU定时器初始化为默认状态
void InitCpuTimers(void)
{
// CPU Timer 0
CpuTimer0.RegsAddr = &CpuTimer0Regs;
// 初始化定时器0寄存器的地址指针,取CpuTimer0Regs地址.
CpuTimer0Regs.PRD.all = 0xFFFFFFFF;
// 将定时器周期初始化成最大值
// Initialize pre-scale counter to divide by 1 (SYSCLKOUT):
CpuTimer0Regs.TPR.all = 0; // 初始化pre-scale(预定标)计数器
CpuTimer0Regs.TPRH.all = 0;
CpuTimer0Regs.TCR.bit.TSS = 1; // (确定)定时器停止
CpuTimer0Regs.TCR.bit.TRB = 1; // 用周期值从新装载所有计数器寄存器
CpuTimer0.InterruptCount = 0; // 复位中断计数器 /*定时器1及定时器2保留用作DSP BIOS及其他实时操作系统,如果你计划要用到DSP-BIOS 或者另外的实时操作系统,请不要使用这两个定时器。 由于这个原因,使用到这两个定时器的 代码都给出注释并在本范例不予使用。*/
// 初始化各个定时寄存器的地址指针
//CpuTimer1.RegsAddr = &CpuTimer1Regs;
//CpuTimer2.RegsAddr = &CpuTimer2Regs;
// Initialize timer period to maximum:
//CpuTimer1Regs.PRD.all = 0xFFFFFFFF; // 将定时器周期初始化成最大值
//CpuTimer2Regs.PRD.all = 0xFFFFFFFF;
// Make sure timers are stopped:
//CpuTimer1Regs.TCR.bit.TSS = 1; // (确定)定时器停止
//CpuTimer2Regs.TCR.bit.TSS = 1;
//CpuTimer1Regs.TCR.bit.TRB = 1; // 用周期值从新装载所有计数寄存器
//CpuTimer2Regs.TCR.bit.TRB = 1;
// Reset interrupt counters:
//CpuTimer1.InterruptCount = 0; // 复位中断指针
//CpuTimer2.InterruptCount = 0; }
/****************************************************************************
函数: ConfigCpuTimer():
功能: 配置Cpu定时器
说明: 这个函数通过"Freq"及"Period"参数选择定时器周期。"Freq"输入单位为
"MHz","Period"输入单位为微秒。配置后定时器参数将保持到到停止状态。
指令注解:
"struct CPUTIMER_VARS *Timer"
* 为指针运算符,Timer(可用其他字母替代)是一个具有CPUTIMER_VARS结
构体类型的指针变量,它指向结构体CPUTIMER_VARS。通过(*Timer).xxx 可以
访问CPUTIMER_VARS结构体中的xxx成员。在C语言中,为了使用方便和使之直
观,可以把(*Timer).xxx改用 Timer->xxx 来代替。"->" 是成员选择(指针)。
有了这个基本概念之后,再来看下面的指令:
Timer->RegsAddr->TCR.bit.TRB = 1;
为了弄清前面两个指针的含义,先引入结构体CPUTIMER_VARS有关定义:
struct CPUTIMER_VARS //该函数由DSP281x_CpuTimers.h文件建立
{
volatile struct CPUTIMER_REGS *RegsAddr;
Uint32 InterruptCount;
float CPUFreqInMHz;
float PeriodInUSec;
};
这个结构体列出了CPU 定时器所支持的变量。其第一个成员是一个包含CPU
定时器所有寄存器的寄存器类型的结构体(CPUTIMER_REGS),RegsAddr 是一个具
有CPUTIMER_REGS结构体类型的指针变量。其他3个成员与定时器寄存器有联系,
但不属于定时器寄存器类型。InterruptCount 是定时器中断计数器,另外两个
的乘积构成定时器的周期。这里把与一个结构体类型相关的变量归入一个结构体
内,这种设计
是值得借鉴的。
现在再引入CPU定时器寄存器结构体CPUTIMER_REGS有关定义:
struct CPUTIMER_REGS // 该函数由DSP281x_CpuTimers.h文件建立
{
union TIM_GROUP TIM; // 定时器计数寄存器
union PRD_GROUP PRD; // 定时器周期寄存器
union TCR_REG TCR; // 定时器控制寄存器
Uint16 rsvd1; // 保留
union TPR_REG TPR; // 定时器预定标计数低位
union TPRH_REG TPRH; // 定时器预定标计数高位
};
这个结构体声明有6个成员,除第4个成员保留外,其余5个均属CPU定时器
特殊寄存器类型的共用体。其中,union TCR_REG TCR; 声明TCR_REG是一种共
用体类型,同时定义相应的共用体变量TCR,以便引用(注意: 不可直接引用一
个类型)。下面列出TCR_REG共用体类型定义及TCR控制寄存器位结构(TCR_BITS)
定义。
// 定义TCR_REG共用体类型。它包含2个成员,一个是16位无符号整数all,
// 一个是16位TCR_BITS结构体,他们共占同一个内存单元。
union TCR_REG //该函数由DSP281x_CpuTimers.h文件建立
{
Uint16 all;
struct TCR_BITS bit;
};
// TCR控制寄存器位结构(TCR_BITS)定义。它是此类数据结构的底层定义。
struct TCR_BITS //该函数由DSP281x_CpuTimers.h文件建立
{ // 位描述
Uint16 rsvd1:4; // 3:0 reserved
Uint16 TSS:1; // 4 Timer Start/Stop
Uint16 TRB:1; // 5 Timer reload
Uint16 rsvd2:4; // 9:6 reserved
Uint16 SOFT:1; // 10 Emulation modes
Uint16 FREE:1; // 11
Uint16 rsvd3:2; // 12:13 reserved
Uint16 TIE:1; // 14 Output enable
Uint16 TIF:1; // 15 Interrupt flag
};
现在再来看指令: Timer->RegsAddr->TCR.bit.TRB = 1;
这条指令最终访问的是TCR寄存器的TRB位。其中Timer指向CPU定时器变量
(CPUTIMER_VARS),RegsAddr指向CPUTIMER_VARS中的CPU定时器寄存器结构体
(CPUTIMER_REGS),后面的关系就比较清楚了。这种访问方法从外层入手,一层
一层地最后进入最内层。
*****************************************************************************/
void ConfigCpuTimer(struct CPUTIMER_VARS *Timer, float Freq, float Period)
{
Uint32 temp;
// 定时器周期初始化
// 将后两个实参的乘积作为定时器的周期值存入定时器周期寄存器
Timer->CPUFreqInMHz = Freq;
Timer->PeriodInUSec = Period;
temp = (long) (Freq * Period);
Timer->RegsAddr->PRD.all = temp;
// 将定时器预定标计数器时钟源周期设置成可被一个处理器时钟
// (SYSCLKOUT)整除。
//Timer->RegsAddr->TPR.all = 0;
//Timer->RegsAddr->TPRH.all = 0;
/****************************************************************************
以下3条指令可代替上面两条指令
****************************************************************************/
CpuTimer0.RegsAddr = &CpuTimer0Regs; // 取CpuTimer0Regs地址
CpuTimer0Regs.TPR.all = 0x0080; // TDDR = 0x xx80
CpuTimer0Regs.TPRH.all = 0x0000; // TDDRH= 0x xx00
// 分频器值 TDDRH:TDDR=0x0080
// Initialize timer control register:
// 定时器控制寄存器初始化。"."是成员(分量)运算符,
// 它在所有运算符中优先级最高
Timer->RegsAddr->TCR.bit.TSS = 1; // 停止定时器。
Timer->RegsAddr->TCR.bit.TRB = 1; // 重装定时器
Timer->RegsAddr->TCR.bit.SOFT = 1;
Timer->RegsAddr->TCR.bit.FREE = 1; // 定时器自由运行
Timer->RegsAddr->TCR.bit.TIE = 1; // 使能定时器中断
Timer->InterruptCount = 0; // 复位中断计数器
}
//===========================================================================
// No more.
//===========================================================================
实验2 GPIO实验
一、GpioLoopback实验
文件: GpioLoopback.c
内容: DSP281x GPIO 回送测试程序
条件与操作方法:
本程序需要DSP281x V1.00头文件支持,另外还需配置成"boot to H0"操作方式。
除此之外引脚引导方式不需要其他硬件配置。
要使实验正常进行,需要将硬件按下面的描述进行配置:
1. 在这个试验中,GPIO 端口中的8位配置成输出,同一端口8位配制成输入.配置
成输出的引脚需要从外部回馈给配置成输入的引脚。输出数据在输入引脚读出。这
种测试对A,B及F端口以不同的数据重复进行。
2. 对D,E及G端口进行类似的写测试。
3. 对A,B及F端口的测试通过单独的一个函数进行访问。在对指定的端口进行测试
之前,必须确定外部的回送。
4. 对于测试状态可查阅全局变量的.ebss空间。
5. 如果 PASS_flag = 0xDOBE 所有测试通过。
6. 如果 PASS_flag = 0xDEAD 则有些试验没有通过。
7. 测试是自行确认的。如果一个测试通过,测试状态序列将会有测试码0x00xx.如
果这个序列是0xDEAD,测试即告失败。
测试 1: 将端口A 高8位配置成输出,低8位配制成输入。将[15:8]位回送到[7:0]位。
QUALPRD=0。在清除/设置/触发指令之间需要加一个延时。该测试运行4次。
测试 2: 将端口A 高8位配置成输入,低8位配制成输出。将[7:0]位回送到[15:8]位。
输入限制周期QUALPRD=0。在清除/设置/触发指令之间需要加一个延时。该测试运行4次。
测试 3: 将端口A 高8位配置成输出,低8位配制成输入。将[15:8]位回送到[7:0]位。
输入限制周期:QUALPRD = 1。在清除/设置/触发指令之间需要加一个延时。为了通过,延
时必须>=( 6 * 2 * QUALPRD ) CPU时钟周期,也就是延时必须>=12个CPU时钟周期。这一
测试运行4次。
测试 4: 将端口B 高8位配置成输出,低8位配制成输入。将[15:8]位回送到[7:0]位。
输入限制周期:QUALPRD = 2。为了通过,延时必须>=24 个CPU 时钟周期。在清除/设置
/触发指令之间需要加一个延时。这一测试运行4次。
测试 5: 将端口F 高7位配置成输出,低8位配制成输入。将[14:8]位回送到[6:0]位,
也可将8位回送到7位。在清除/设置/触发指令之间需要加一个延时。这一测试运行4次。 ********************************************************************************************
#include "DSP281x_Device.h" // DSP281x 头文件包含文件
#include "DSP281x_Examples.h" // DSP281x 示例包含文件
// 由本文件建立的函数原型声明。
void delay_loop(void); // 延时
void Gpio_select(void); // Gpio配置函数
void error(int); // 错误处理函数
void program_stop(); // 程序终止函数
void Gpio_PortA(void); // Gpio A口回送测试函数
void Gpio_PortB(void); // Gpio B口回送测试函数
void Gpio_PortF(void); // Gpio F口回送测试函数
// 由文件Bc7281.c 建立的外部函数
//void LedD_Display(void);
// 将模数转换值以10进制形式,在Led第4,3,2,1位数码管上进行显示 //void LedH_Display(void) ;
// 将模数转换值以16进制两个字节形式,在Led第8,7,6,5位数码管上进行显示
// 全局变量声明
Uint16 var1 = 0;
Uint16 var2 = 0;
Uint16 var3 = 0;
Uint16 test_count = 0;
Uint16 Test_flag = 0;
Uint16 Test_var = 0;
Uint16 Test_status[32];
// 定义一个由32个无符号16位数组成的数组,数组的32个元素分别是
// Test_status[0],Test_status[1],... ,Test_status[31] Uint16 PASS_flag = 0;
Uint16 count=0; // Led数码管显示用
void main(void)
{
// 步骤1:系统控制初始化。
InitSysCtrl(); // 锁相环(PLL),看门狗(WatchDog)及外设时钟(PeripheralClocks)
// 初始化。InitSysCtrl()函数由DSP281x_SysCtrl.c文件建立。
// 步骤2:初始化GPIO。
// InitGpio(); // 本例跳过这个函数。该函数例举怎样将GPIO设置成其默认方式,
// 该函数由DSP281x_Gpio.c文件建立。
// 步骤3:清所有中断并初始化PIE向量表 。
DINT; // 关CPU中断。
InitPieCtrl(); // 初始化PIE控制寄存器为默认状态,即关所有PIE中断并清除所有标志。
// 这个函数由DSP281x_PieCtrl.c文件建立。
IER = 0x0000;
IFR = 0x0000; // 关CPU中断并清所有CPU中断标识符。
InitPieVectTable(); // 初始化PIE向量表,该向量表指出中断服务程序(ISR)的构架。
// ISR程序构架由DSP281x_DefaultIsr.c文件建立。
// 为方便调试,即使本例不用中断,仍然板上组装整个PIE向量表。
// InitPieVectTable()函数由DSP281x_PieVect.c文件建立
// 步骤4:初始化器件所有外设。
// InitPeripherals();
// 该函数由DSP281x_InitPeripherals.c文件建立。
// 本例不需要这个函数。
// 步骤5:用户代码。
Gpio_PortA(); // Tests #1, #2, #3
Gpio_PortB(); // Test #4
Gpio_PortF(); // Test #5
//program_stop();
// 步骤6: 无限空循环
for(;;);
}
// 步骤 7. 嵌入所有局部中断服务程序及函数:
/*******************************************************************************************
函数名称: Gpio_PortA(void)
函数功能: Gpio A口回送测试
*******************************************************************************************/
void Gpio_PortA(void)
{
/*******************************************************************************************
GPIO 测试 #1:将端口A 高8位配置成输出,低8位配制成输入。将[15:8]位回送到[7:0]位。
设置限制周期QUALPRD为0。
*******************************************************************************************/
var1= 0x0000; // 将GPIO 功能选择控制寄存器配置成I/O 模式
var2= 0xFF00; // 将GPIO 15-8位方向配置成输出,7-0位方向配置成输入。
var3= 0x0000; // 设置限制周期QUALPRD为0。
Gpio_select();
test_count = 0;
Test_status[Test_var] = 0x0001; //Test_status[0]=0x0001
Test_var++; //Test_var=1
Test_status[Test_var] = 0xD0BE; // 设置状态缺省值成"PASSED", 0xD0BE为测试通过的标示值。
while (test_count < 4) // 重复测试4次
{
/****** 清除测试 ******/
GpioDataRegs.GPACLEAR.all = 0xFF00;
// GPIOA 高8位清除,即高8位引脚置成低电平,低8位无影响。
asm(" RPT #5 ||NOP"); // C代码汇编语言嵌入方式。重复执行
// 5条NOP指令,用于延时。
Test_flag = GpioDataRegs.GPADAT.all;
// 读出GPIOA 口数据并存入Test_flag。由于前面已经将高8位置
// 成低电平,且高8位已连接到低8位,故GPIOA=0x0000。
if ( Test_flag != 0x0000 ) error(1);
// 如果 Test_flag != 0x0000,执行出错处理,否则跳转下一条指令
/****** 设置测试 ******/
GpioDataRegs.GPASET.all = 0x5500;
// 将GPIOA 口的第15,13,11,9(第16位为最高位)置成高电平,
// 其余制置成低电平。
asm(" RPT #5 ||NOP"); // 重复执行5条NOP指令,用于延时。
Test_flag = GpioDataRegs.GPADAT.all;
// 读出GPIOA口数据并存入Test_flag。在正常情况下Test_flag = 0x5555
if ( Test_flag != 0x5555 ) error(1);
// 如果 Test_flag != 0x5555,执行出错处理,否则跳转下一条指令。
/****** 触发测试 ******/
GpioDataRegs.GPATOGGLE.all = 0xFF00;
// 将GPIOA 口高8位置反,低8位不受影响,由于前面GPIOA = 0x5555
// 且高8位已连接到低8位,故GPIOA = 0xAAAA。
asm(" RPT #5 ||NOP"); // 重复执行5条NOP指令,用于延时。
Test_flag = GpioDataRegs.GPADAT.all;
// 读出GPIOA 口数据并存入Test_flag?
if ( Test_flag != 0xAAAA ) error(1);
// 如果 Test_flag != 0xAAAA,执行出错处理,否则跳转下一条指令。
test_count++; // test_count加1。
}
Test_var++; // 重复4次完成后,Test_var=2 // 测试 #1 结束。
/*******************************************************************************************
GPIO 测试 #2:将端口高8位配置成输入,低8位配制成输出。将[7:0]位回送到[15:8]位。
设置限制周期QUALPRD为0。
*******************************************************************************************/
var1= 0x0000; // 将GPIO 功能选择控制寄存器配置成I/O 模式
var2= 0x00FF; // 将GPIO 15-8位方向配置成输入,7-0位方向配置成输出。
var3= 0x0000; // 设置限制周期QUALPRD为0。
Gpio_select(); // Gpio 设置。见Gpio_select()函数。
test_count = 0;
Test_status[Test_var] = 0x0002;
Test_var++;
Test_status[Test_var] = 0xD0BE; // 将0xD0BE设置成状?PASSED"
while (test_count < 4) // 重复测试4次
{
/****** 清除测试 ******/
GpioDataRegs.GPACLEAR.all = 0x00FF;
// GPIOA 低8位清除,即低8位引脚置成低电平,高8位办。L1-L1
asm(" RPT #5 ||NOP");
Test_flag = GpioDataRegs.GPADAT.all;
// 读出GPIOA 口数据并存入Test_flag。由于前面已经将低8位置
// 成低电平,且低8位已连接到高8位,故GPIOA 口数据为0。
if ( Test_flag != 0x0000 ) error(1);
/****** 设置测试 ******/
GpioDataRegs.GPASET.all = 0x00AA;
// 将GPIOA 口的第8,6,4,2(第1位为最低位)置成高电平,
// 其余制置成低电平。
asm(" RPT #5 ||NOP");
Test_flag = GpioDataRegs.GPADAT.all;
// 读出GPIOA口数据并存入Test_flag。由于已将第8,6,4,2置成高
// 电平,且低8位已连接到高8位,故GPIOA = 0xAAAA。
if ( Test_flag != 0xAAAA ) error(1);
/****** 触发测试 ******/
GpioDataRegs.GPATOGGLE.all = 0x0055;
// 将GPIOA 第7,5,3,1位置反,其余位不受影响,由于前面GPIOA = 0xAAAA,
// 故GPIOA = 0xAAFF,又由于低8位已连接到高8位,故GPIOA = 0xFFFF。
asm(" RPT #5 ||NOP");
Test_flag = GpioDataRegs.GPADAT.all;
if ( Test_flag != 0xFFFF ) error(1);
test_count++;
}
Test_var++;
// 测试 #2 结束
/*******************************************************************************************
GPIO 测试 #3:将端口高8位配置成输出,低8位配制成输入。将[15:8]位回送到[7:0]位。
设置输入限制周期QUALPRD成0x0001。
*******************************************************************************************/
var1= 0x0000; // 将GPIO 功能选择控制寄存器配置成I/O 模式
var2= 0xFF00; // 将GPIO 15-8位方向配置成输出,7-0位方向配置成输入。
var3= 0x0001; // 设置输入限制周期QUALPRD成0x0001。
Gpio_select(); // Gpio 设置。见Gpio_select()函数。
// 测试 #3A: 设置延时以便隔离输入。
// 延时必须<( 6 * 2 * QUALPRD ) CPU时钟周期。
Test_status[Test_var] = 0x0003;
Test_var++;
Test_status[Test_var] = 0xD0BE; // 将0xD0BE设置成状态缺省值"PASSED"
test_count = 0;
while (test_count < 4) // 重复测试4次
{
GpioDataRegs.GPBSET.all = 0xFF00;
// 将GPIOB 高8位设置成高电平,低8位无影响。由于高8位与低8位对应
// 相连,故GPIOB 口均呈高电平。
delay_loop();
/****** 清除测试 ******/
GpioDataRegs.GPACLEAR.all = 0xFF00;
// 将GPIOA 高8位设置成低电平。由于高8位与低8位对应相连,故GPIOB 口
// 均呈低电平。
asm (" RPT #14 || NOP"); // 延时< ( 6 * 2 ) CPU时钟周期
Test_flag = GpioDataRegs.GPADAT.all;
//if ( Test_flag == 0x0000 ) error(1); // 原指令
if ( Test_flag != 0x0000 ) error(1); // 修改指令
/****** 设置测试 ******/
GpioDataRegs.GPASET.all = 0x5500;
// 将GPIOA 第15,13,11,9位设置成高电平。由于高8位与低8位对应相
// 连,故GPIOA=0x5555。
asm(" RPT #14 ||NOP");
Test_flag = GpioDataRegs.GPADAT.all;
//if ( Test_flag == 0x5555 ) error(1); // 原指令
if ( Test_flag != 0x5555 ) error(1); // 修改指令
/****** 触发测试 ******/
GpioDataRegs.GPATOGGLE.all = 0xFF00;
// 将GPIOA 高8位置反,其余位不受影响,由于前面GPIOA = 0x5555,
// 故GPIOA = 0xAA55,又由于低8位已连接到高8位,故GPIOA = 0xAAAA。
asm(" RPT #14 ||NOP");
Test_flag = GpioDataRegs.GPADAT.all;
//if ( Test_flag == 0xAAAA ) error(1); // 原指令
if ( Test_flag != 0xAAAA ) error(1); // 修改指令
test_count++;
}
Test_var++;
// 测试 3B: 设置延时以便输入顺利地被量化。
// 延时必须 >= ( 6 * 2 * QUALPRD ) CPU时钟周期。
Test_status[Test_var] = 0x0004;
Test_var++;
Test_status[Test_var] = 0xD0BE; // 将0xD0BE设置成状态缺省值"PASSED"
test_count = 0;
while (test_count < 4) // 重复测试4次
{
GpioDataRegs.GPASET.all = 0xFF00;
// 将GPIOA 高8位设置成高电平。由于高8位与低8位对应相
// 连,故GPIOA=0xFFFF。
delay_loop();
/****** 清除测试 ******/
GpioDataRegs.GPACLEAR.all = 0xFF00;
// 将GPIOA 高8位设置成低电平。由于高8位与低8位对应相
// 连,故GPIOA=0x0000。
asm (" RPT #16 || NOP"); // 延时= ( 6 * 2 * 1 ) CPU时钟周期
Test_flag = GpioDataRegs.GPADAT.all;
if ( Test_flag != 0x0000 ) error(1);
/****** 设置测试 ******/
GpioDataRegs.GPASET.all = 0x5500;
// 将GPIOA 第15,13,11,9位设置成高电平。由于高8位与低8位对应相
// 连,故GPIOA=0x5555。
asm(" RPT #16 ||NOP");
Test_flag = GpioDataRegs.GPADAT.all;
if ( Test_flag != 0x5555 ) error(1);
/****** 触发测试 ******/
GpioDataRegs.GPATOGGLE.all = 0xFF00;
// 将GPIOA 高8位置反,其余位不受影响,由于前面GPIOA = 0x5555,
// 故GPIOA = 0xAA55,又由于低8位已连接到高8位,故GPIOA = 0xAAAA。
asm(" RPT #16 ||NOP");
Test_flag = GpioDataRegs.GPADAT.all;
if ( Test_flag != 0xAAAA ) error(1);
test_count++;
}
Test_var++;
}
// 测试 #3 结束
/*******************************************************************************************
函数名称: Gpio_PortB(void)
函数功能: Gpio B口回送测试
输入参数: 无
输出参数: 无
*******************************************************************************************/
void Gpio_PortB(void)
{
/*******************************************************************************************
GPIO 测试 #4:将端口B 高8位配置成输出,低8位配制成输入。将[15:8]位回送到[7:0]位。
设置输入限制周期QUALPRD为0x0002。
*******************************************************************************************/
var1= 0x0000; // 将GPIO 功能选择控制寄存器配置成I/O 模式
var2= 0xFF00; // 将GPIO 15-8位方向配置成输出,7-0位方向配置成输入
var3= 0x0002; // 设置输入限制周期QUALPRD为0x0002。
Gpio_select(); // Gpio 设置。见Gpio_select()函数。 // 测试 #4A: 设置延时以便隔离输入。
// 延时必须<( 6 * 2 * QUALPRD ) CPU时钟周期。
Test_status[Test_var] = 0x0005;
Test_var++;
Test_status[Test_var] = 0xD0BE; // 将0xD0BE设置成状态缺省值"PASSED"
test_count = 0;
while (test_count < 4) // 重复测试4次
{
GpioDataRegs.GPBSET.all = 0xFF00;
// 将GPIOB 高8位设置成高电平。由于高8位与低8位对应相
// 连,故GPIOB=0xFFFF。
delay_loop();
/****** 清除测试 ******/
GpioDataRegs.GPBCLEAR.all = 0xFF00;
// 将GPIOB 高8位设置成低电平。由于高8位与低8位对应相
// 连,故GPIOB=0x0000。
asm (" RPT #24 || NOP"); // 延时< ( 6 * 2 * 2 ) CPU时钟周期
Test_flag = GpioDataRegs.GPBDAT.all;
//if ( Test_flag == 0x0000 ) error(1); // 原指令
if ( Test_flag != 0x0000 ) error(1); // 修改指令
/****** 测试设置 ******/
GpioDataRegs.GPBSET.all = 0x5500;
// 将GPIOB 第15,13,11,9位设置成高电平。由于高8位与低8位对应相
// 连,故GPIOB=0x5555。
asm(" RPT #24 ||NOP");
Test_flag = GpioDataRegs.GPBDAT.all;
//if ( Test_flag == 0x5555 ) error(1); // 原指令
if ( Test_flag != 0x5555 ) error(1); // 修改指令
/****** 触发测试 ******/
GpioDataRegs.GPBTOGGLE.all = 0xFF00;
// 将GPIOB 高8位置反,其余位不受影响,由于前面GPIOA = 0x5555,
// 故GPIOB = 0xAA55,又由于低8位已连接到高8位,故GPIOB = 0xAAAA。
asm(" RPT #24 ||NOP");
Test_flag = GpioDataRegs.GPBDAT.all;
//if ( Test_flag == 0xAAAA ) error(1); // 原指令
if ( Test_flag != 0xAAAA ) error(1); // 修改指令
test_count++;
}
Test_var++;
// 测试 #4B: 设置延时以便输入顺利地被量化。
// 延时必须 >= ( 6 * 2 * QUALPRD ) CPU时钟周期。
Test_status[Test_var] = 0x0006;
Test_var++;
Test_status[Test_var] = 0xD0BE; // 将0xD0BE设置成状态缺省值"PASSED"
test_count = 0;
while (test_count < 4) // 重复测试4次
{
GpioDataRegs.GPBSET.all = 0xFF00;
// 将GPIOB 高8位设置成高电平。由于高8位与低8位对应相
// 连,故GPIOB=0xFFFF。
delay_loop();
/****** 清除测试 ******/
GpioDataRegs.GPBCLEAR.all = 0xFF00;
// 将GPIOB 高8位设置成低电平。由于高8位与低8位对应相
// 连,故GPIOB=0x0000。
asm (" RPT #29 || NOP"); // 延时= (6 * 2 * 2) CPU时钟周期
Test_flag = GpioDataRegs.GPBDAT.all;
if ( Test_flag != 0x0000 ) error(1);
/****** 设置测试 ******/
GpioDataRegs.GPBSET.all = 0x5500;
// 将GPIOB 第15,13,11,9位设置成高电平。由于高8位与低8位对应相
// 连,故GPIOB=0x5555。
asm(" RPT #29 ||NOP");
Test_flag = GpioDataRegs.GPBDAT.all;
if ( Test_flag != 0x5555 ) error(1);
/****** 触发测试 ******/
GpioDataRegs.GPBTOGGLE.all = 0xFF00;
// 将GPIOB 高8位置反,其余位不受影响,由于前面GPIOA = 0x5555,
// 故GPIOB = 0xAA55,又由于低8位已连接到高8位,故GPIOB = 0xAAAA。
asm(" RPT #29 ||NOP");
Test_flag = GpioDataRegs.GPBDAT.all;
if ( Test_flag != 0xAAAA ) error(1);
test_count++;
}
Test_var++;
}
// 测试 #4 结束
/*******************************************************************************************
函数名称: Gpio_PortF(void)
函数功能: Gpio F口回送测试
输入参数: 无
输出参数: 无
*******************************************************************************************/
void Gpio_PortF(void)
{
/*******************************************************************************************
GPIO 测试 #5:将端口F 高[14:8]位配置成输出,[7:0]位配制成输入。将[14:8]位
回送到[6:0]位,也可以将8位回送到7位
*******************************************************************************************/
var1= 0x0000; // 将GPIO 功能选择控制寄存器配置成I/O 模式
var2= 0xFF00; // 将GPIO 14-8位方向配置成输出,7-0位方向配置成输入。
Gpio_select(); // Gpio 设置。见Gpio_select()函数。
Test_status[Test_var] = 0x0007;
Test_var++;
Test_status[Test_var] = 0xD0BE; // 将0xD0BE设置成状态缺省值"PASSED"
test_count = 0;
while (test_count < 4) // 重复测试4次
{
GpioDataRegs.GPFSET.all = 0xFF00;
// 将GPIOF 高8位设置成高电平。由于高8位与低8位对应相
// 连,故GPIOF=0xFFFF。
delay_loop();
/****** 清除测试 ******/
GpioDataRegs.GPFCLEAR.all = 0xFF00;
// 将GPIOF 高8位设置成低电平。由于高8位与低8位对应相
// 连,故GPIOF=0x0000。
asm (" RPT #6 || NOP");
Test_flag = GpioDataRegs.GPFDAT.all;
if ( Test_flag != 0x0000 ) error(1);
/****** 设置测试 ******/
GpioDataRegs.GPFSET.all = 0x5500;
// 将GPIOF 第15,13,11,9位(最高位为第16位)设置成高电平。由于
// 高8位与低8位相连,且第16位为空(输出为0),故GPIOF=0x5555。
asm(" RPT #6 || NOP");
Test_flag = GpioDataRegs.GPFDAT.all;
if ( Test_flag != 0x55D5 ) error(1); //???????????
/****** 触发测试 ******/
GpioDataRegs.GPFTOGGLE.all = 0xFF00;
// 将GPIOF 高8位置反,其余位不受影响,由于前面GPIOA = 0x5555,
// 故GPIOB = 0x2A55(第16位为空,输出为0),又由于低8位已连接到
// 高8位,故GPIOB = 0x2A2A。
asm(" RPT #6 || NOP");
Test_flag = GpioDataRegs.GPFDAT.all;
if ( Test_flag != 0x2A2A ) error(1);
test_count++;
}
Test_var++;
}
// 测试 #5 结束
/*******************************************************************************************
函数名称: delay_loop()
函数功能: 简单延时函数
输入参数: 无
输出参数: 无
*******************************************************************************************/
void delay_loop()
{
short i;
for (i = 0; i < 1000; i++) {}
}
/*******************************************************************************************
函数: Gpio_select()
功能: (1) 将所有功能选择控制寄存器GPxMUX配置成I/O功能,由var1=0x0000
确定;
(2) 将同一方向控制寄存器GPxDIR配置成部分数字量输出及部分数字量
输入。若某位为1,则对应位为输出,否则为输入;
(3) 配置相应的输入量化控制寄存器GPxQUAL; P617
以上3种寄存器有EALLOW保护功能。
*******************************************************************************************/
void Gpio_select(void)
{
EALLOW;
GpioMuxRegs.GPAMUX.all=var1; // 将GPIO 功能选择控制寄存器配置成数字
// I/O 口或外设I/O口。
GpioMuxRegs.GPBMUX.all=var1;
GpioMuxRegs.GPDMUX.all=var1;
GpioMuxRegs.GPFMUX.all=var1;
GpioMuxRegs.GPEMUX.all=var1;
GpioMuxRegs.GPGMUX.all=var1;
GpioMuxRegs.GPADIR.all=var2; // 通过设置GPIO方向寄存器,设置GPIO端口
// 为输入或输出
GpioMuxRegs.GPBDIR.all=var2;
GpioMuxRegs.GPDDIR.all=var2;
GpioMuxRegs.GPEDIR.all=var2;
GpioMuxRegs.GPFDIR.all=var2;
GpioMuxRegs.GPGDIR.all=var2;
GpioMuxRegs.GPAQUAL.all=var3; // 设置GPIO输入限制周期QUALPRD值
GpioMuxRegs.GPBQUAL.all=var3;
GpioMuxRegs.GPDQUAL.all=var3;
GpioMuxRegs.GPEQUAL.all=var3;
EDIS;
}
/*******************************************************************************************
函数: error()
功能: 出错处理函数
*******************************************************************************************/
void error (int ErrorFlag)
{
PASS_flag = 0xDEAD;
Test_status[Test_var] = 0xDEAD; // 0xD0BE为测试失败的标示值。
return; // 返回运行程序
}
/*******************************************************************************************
函数: program_stop()
功能: 程序终止函数
*******************************************************************************************/
void program_stop()
{
// 进行所有测试
if(PASS_flag !=0) PASS_flag=0xDEAD; // Test code exit here..
else PASS_flag=0xD0BE; // Test code exit he
// 终止所有测试
asm(" ESTOP0"); // Done!
for(;;) { } // Dummy loop Wait forever
}
//================================================================================
// No more.
//================================================================================
二、GpioToggle实验
文件: GpioToggle.c
内容: DSP281x 器件GPIO触发测试程序。
条件: 本程序需要DSP281x V1.00头文件支持,另外还需配置成"boot to H0"操作方式。除此之外引脚
引导方式不需要其他硬件配置。
说明: 这里包含了(数据寄存器方式、设置/清除寄存器方、触发寄存器方式及GPIO A 流水灯试验)4个
例子,可在编译前通过对程序开头#define声明选择执行其中的一个.触发所有的GPIO引脚。通过示
波器观察引脚。
*******************************************************************************************/
#include "DSP281x_Device.h" // DSP281x 头文件包含文件
#include "DSP281x_Examples.h" // DSP281x 示例包含文件
// 选择例子进行编译。仅有一个例子设置为1,其余的设置为0
#define EXAMPLE1 0 // 用数据寄存器触发I/O引脚
#define EXAMPLE2 0 // 用设置/清除存器触发I/O引脚
#define EXAMPLE3 0 // 用触发寄存器触发I/O引脚
#define MyExample 1 // 16个发光二极管LED1(L1)-LED16(L16)流水灯实验
// 本文件建立的函数原型声明
void delay_loop(void);
void Gpio_select(void); // Gpio 配置函数
void Gpio_example1(void); // 用数据寄存器触发I/O引脚函数
void Gpio_example2(void); // 用设置/清除存器触发I/O引脚
void Gpio_example3(void); // 用触发寄存器触发I/O引脚
void Gpio_MyExample(void); // 16个发光二极管LED1(L1)-LED16(L16)流水灯实验 void main(void)
{
// 步骤1:系统控制初始化。
InitSysCtrl(); // 锁相环(PLL),看门狗(WatchDog)及外设时钟(PeripheralClocks)
// 初始化。InitSysCtrl()函数由DSP281x_SysCtrl.c文件建立。
// 步骤2:初始化GPIO。
// InitGpio(); // 本例跳过这个函数。该函数例举怎样将GPIO设置成其默认方式,
// 该函数由DSP281x_Gpio.c文件建立。
Gpio_select(); // 本例要用到的配置。
// 步骤3:清所有中断并初始化PIE向量表 。
DINT; // 关CPU中断。
IER = 0x0000;
IFR = 0x0000; // 关CPU中断并清所有CPU中断标识符。
InitPieVectTable(); // 初始化PIE向量表,该向量表指出中断服务程序(ISR)的构架。
// ISR程序构架由DSP281x_DefaultIsr.c文件建立。
// 为方便调试,即使本例不用中断,仍然板上组装整个PIE向量表。
// InitPieVectTable()函数由DSP281x_PieVect.c文件建立
// 步骤4:初始化器件所有外设。
// InitPeripherals();
// 该函数由DSP281x_InitPeripherals.c文件建立。
// 本例不需要这个函数。
// 步骤5:用户代码。
#if EXAMPLE1 // 如果仅仅EXAMPLE1=1(为真),执行Gpio_example1()并终止if判
// 断语句;
Gpio_example1(); // 本例采用DATA(数据)寄存器方式触发I/0引脚 #endif
#if EXAMPLE2 // 如果仅仅EXAMPLE2=1(为真),执行Gpio_example2()并终止if判
// 断语句;
Gpio_example2(); // 本例采用SET/CLEAR(设置/清除)寄存器方式触发I/0引脚 #endif
#if EXAMPLE3 // 如果仅仅EXAMPLE3=1(为真),执行Gpio_example3()并终止if判
// 断语句; 执行最前面的一个if语句
Gpio_example3(); // 本例采用TOGGLE(触发)寄存器方式触发I/0引脚 #endif
#if MyExample // 如果仅仅MyExample=1(为真),执行Gpio_MyExample()。
Gpio_MyExample(); // 若均为1则只执行Gpio_example1()。
#endif
}
/*******************************************************************************************
函数名称: Gpio_example1(void)
函数功能: 采用数据寄存器方式触发I/O引脚
输入参数: 无
输出参数:
注 意: 当采用数据寄存器时,输入值可能会丢失. 如果端口有数据输入则采用清除/设置/触发寄存
器替代.函数中牵涉到的寄存器不受EALLOW保护,可正常访问GPIO A口可通过16个发光二
极管LED1(L1)-LED16(L16)观察,其他各口可通过示波器观察。
*******************************************************************************************/
void Gpio_example1(void)
{
for(;;) // for(;;)及while(1)均为无限循环语句。但用while(1)会出现编译警告。
//while(1)
{
GpioDataRegs.GPADAT.all =0xAAAA;
// GPADAT(GPIO A 数据寄存器)
// 如果GPIO A某引脚已配置成数字量输出,则对GPADAT的对某位写1后,相应引脚将
// 被拉高,对应Lx灭;写0相应引脚将被拉低,对应Lx亮。
GpioDataRegs.GPBDAT.all =0xAAAA;
GpioDataRegs.GPDDAT.all =0x0022;
GpioDataRegs.GPEDAT.all =0x0002;
GpioDataRegs.GPFDAT.all =0xAAAA;
GpioDataRegs.GPGDAT.all =0x0020;
delay_loop();
GpioDataRegs.GPADAT.all =0x5555; // A口有16个 I/O 引脚。
GpioDataRegs.GPBDAT.all =0x5555; // B口有16个 I/O 引脚。
GpioDataRegs.GPDDAT.all =0x0041; // D口只有4个 I/O 引脚。
GpioDataRegs.GPEDAT.all =0x0005; // E口只有3个 I/O 引脚。
GpioDataRegs.GPFDAT.all =0x5555; // F口有15个 I/O 引脚。
GpioDataRegs.GPGDAT.all =0x0010; // G口只有2个 I/O 引脚。
delay_loop();
}
}
/*******************************************************************************************
函数名称: Gpio_example2(void)
函数功能: 采用设置/清除寄存器方式触发I/O引脚.
输入参数: 无
输出参数: 无
注 意: 函数中牵涉到的寄存器不受EALLOW保护,可正常访问。
GPIO A口可通过16个发光二极管LED1(L1)-LED16(L16)观察,其他各口可通过示波器察。 *******************************************************************************************/
void Gpio_example2(void)
{
for(;;)
//while(1)
{
GpioDataRegs.GPASET.all =0xAAAA;
// GPASET(GPIO A 置位寄存器). 某位写1后,相应引脚将被置成高电平,对应Lx灭。
// 写0没有影响。
GpioDataRegs.GPACLEAR.all =0x5555;
// GPACLEAR(GPIO A 清除寄存器).
// 如果GPIO A某引脚已配置成数字量输出,则对GPACLEAR的某位写1后,相应引脚将
// 被置成低电平,对应Lx亮。写0没有影响。
GpioDataRegs.GPBSET.all =0xAAAA;
GpioDataRegs.GPBCLEAR.all =0x5555;
GpioDataRegs.GPDSET.all =0x0022;
GpioDataRegs.GPDCLEAR.all =0x0041;
GpioDataRegs.GPESET.all =0x0002;
GpioDataRegs.GPECLEAR.all =0x0005;
GpioDataRegs.GPFSET.all =0xAAAA;
GpioDataRegs.GPFCLEAR.all =0x5555;
GpioDataRegs.GPGSET.all =0x0020;
GpioDataRegs.GPGCLEAR.all =0x0010;
delay_loop();
GpioDataRegs.GPACLEAR.all =0xAAAA;
GpioDataRegs.GPASET.all =0x5555; // A口有16个 I/O 引脚。
GpioDataRegs.GPBCLEAR.all =0xAAAA;
GpioDataRegs.GPBSET.all =0x5555; // B口有16个 I/O 引脚。
GpioDataRegs.GPDCLEAR.all =0x0022;
GpioDataRegs.GPDSET.all =0x0041; // D口只有4个 I/O 引脚。
GpioDataRegs.GPECLEAR.all =0x0002;
GpioDataRegs.GPESET.all =0x0005; // E口只有3个 I/O 引脚。
GpioDataRegs.GPFCLEAR.all =0xAAAA;
GpioDataRegs.GPFSET.all =0x5555; // F口有15个 I/O 引脚。
GpioDataRegs.GPGCLEAR.all =0x0020;
GpioDataRegs.GPGSET.all =0x0010; // G口只有2个 I/O 引脚。 delay_loop();
}
}
/*******************************************************************************************
函数名称: Gpio_example3(void)
函数功能: 采用触发寄存器方式触发I/O引脚。
输入参数: 无
输出参数: 无
注 意: 函数中牵涉到的寄存器不受EALLOW保护,可正常访问GPIO A口可通过16个发光二极
管LED1(L1)-LED16(L16)观察,其他各口可通过示波器观察。
*******************************************************************************************/
void Gpio_example3(void)
{
// 设置以下各口为默认状态
GpioDataRegs.GPASET.all =0xAAAA;
// GPASET(GPIO A 置位寄存器).
// 如果GPIO A某引脚已配置成数字量输出,则对GPASET的某位写1后,相应引脚将被置成
// 高电平,对应Lx灭。写0没有影响。
GpioDataRegs.GPACLEAR.all =0x5555;
// GPACLEAR(GPIO A 清除寄存器).
// 如果GPIO A某引脚已配置成数字量输出,则对GPACLEAR的某位写1后,相应引脚将被置
// 成低电平,对应Lx灭亮。写0没有影响。
GpioDataRegs.GPBSET.all =0xAAAA;
GpioDataRegs.GPBCLEAR.all =0x5555;
GpioDataRegs.GPDSET.all =0x0022;
GpioDataRegs.GPDCLEAR.all =0x0041; // D口只有4个 I/O 引脚。
GpioDataRegs.GPESET.all =0x0002;
GpioDataRegs.GPECLEAR.all =0x0005; // E口只有3个 I/O 引脚。
GpioDataRegs.GPFSET.all =0xAAAA;
GpioDataRegs.GPFCLEAR.all =0x5555; // F口有15个 I/O 引脚。
GpioDataRegs.GPGSET.all =0x0020;
GpioDataRegs.GPGCLEAR.all =0x0010; // G口只有2个 I/O 引脚。
// 采用触发寄存器方式翻转引脚状态。
// 任意位置1将触发翻转引脚状态,任意位置0 将不予触发。
for(;;)
//while(1) // 当括号中的表达式为非零值时,执行while语句中的内嵌语句。由于表达式恒为1,
// 内嵌语句将无限循环。"while(1)"是实现语句无限循环的一种方式。但编译时会发出
// 警告。故改用for(;;)无限循环语句。
{
GpioDataRegs.GPATOGGLE.all = 0xFFFF;
// GPATOGGLE(GPIO A 反转触发寄存器)
// 如果GPIO A某引脚已配置成数字量输出,则对GPATOGGLE的对应位写1后,该引脚
// 信号将被取反.写0没有影响.
GpioDataRegs.GPBTOGGLE.all = 0xFFFF;
GpioDataRegs.GPDTOGGLE.all = 0xFFFF;
GpioDataRegs.GPETOGGLE.all = 0xFFFF;
GpioDataRegs.GPFTOGGLE.all = 0xFFFF;
GpioDataRegs.GPGTOGGLE.all = 0xFFFF;
delay_loop();
}
}
/*******************************************************************************************
函数名称: Gpio_MyExample()
函数功能: 16个发光二极管LED1(L1)-LED16(L16)流水灯实验
输入参数: 无
输出参数: 无
注 意: 函数中牵涉到的寄存器不受EALLOW保护,可正常访问。
GPIO A口可通过16个发光二极管LED1(L1)-LED16(L16)观察,
*******************************************************************************************/
void Gpio_MyExample(void)
// 试验板有16个LED通过2个74HC373锁存器从左到右顺序接到GPIOA0-GPIOA15引脚.
// 引脚为低电平时,点亮LED.GPIOA15对应GpioDataRegs.GPADAT.all中的第16位L16...GPIOA0
// 对应第1位(最低位)L1
{
Uint16 ShiftBuf;
ShiftBuf=0xffff;
GpioDataRegs.GPADAT.all = ShiftBuf; // 16个LED全灭
for(;;)
{
if (ShiftBuf==0xffff)
// 测试count是否为0xffff,若为0xffff,则对count赋初值,否则执行
// else后的语句
{
ShiftBuf=0xfffe; // 首先点亮LED1(L1)
GpioDataRegs.GPADAT.all =ShiftBuf;
delay_loop(); // LED点亮延时
}
else
{
GpioDataRegs.GPADAT.all =ShiftBuf; //点亮对应位为0的LEDx(Lx)
// GPADAT(GPIO A 数据寄存器)
// 如果GPIO A某引脚已配置成数字量输出,则对GPADAT的对
// 应位写1后,相应引脚将被拉高;写0相应引脚将被拉低.
ShiftBuf=ShiftBuf<<1; // count左移一位
ShiftBuf=ShiftBuf+0x0001; // 左移一位后,用1填充最低位(对应L1)
delay_loop(); // LED点亮延时
}
}
}
/*******************************************************************************************
函数名称: Gpio_select()
函数功能:
(1) 将所有功能选择控制寄存器GPxMUX配置成I/O功能,由var1= 0x0000确定;
(2) 将所有方向控制寄存器GPxDIR配置成数字量输出,由var2= 0xFFFF确定;
(3) 将所有输入量化控制寄存器GPxQUAL配置成0x0000,不设置任何输入量化值,只是和
SYSCLKOUT同步; P617
以上3种寄存器有EALLOW保护功能。
DSP2812器件提供56个通用目的数字量I/O引脚。他们是 GPIOA GPIOB 各16个,GPIOD 4个,
GPIOE 3个,GPIOF 15个以及 GPIOG 2个。
这些引脚绝大部分是多功能复用引脚,首先通过以下3个特殊寄存器进行配置。
(1) GPxMUX 功能选择控制寄存器:
* 如果 GPxMUX.bit=0,相应引脚配置为I/O 功能;
* 如果 GPxMUX.bit=1,相应引脚配置为外设功能功能。
(2) GPxDIR 方向控制寄存器:
* 如果 GPxDIR.bit=0,相应引脚配置为数字量输入;
* 如果 GPxDIR.bit=1,相应引脚配置为数字量输出。
(3) GPxQUAL 输入量化寄存器。
* GPxQUAL规定合格的采样周期的大小。一个周期
=SYSCLKOUT/((GPxQUAL[7:0]*2)。
当6个采样周期都相同时(都为1或都为0),输出才会改变。这种特性可去掉混杂在输入信号中
的噪声。
以上3类特殊寄存器有EALLOW保护功能。此功能可防止私自写或覆盖寄存器的内容而破坏系
统。
一旦对引脚功能进行配置后,就可通过以下4个特殊寄存器对引脚进行设置。
(1) GPxDAT 数据寄存器
* GPxDAT.bit=0,且引脚设置为输出,将相应的引脚拉低;
* GPxDAT.bit=1,且引脚设置为输出,将相应的引脚拉高;
(2) GPxSET 置位寄存器
* GPxSET.bit=0,没有影响;
* GPxSET.bit=1,且引脚设置为输出,将相应的引脚置成高电平。
(3) GPxCLEAR 清除寄存器
* GPxCLEAR.bit=0,没有影响;
* GPxCLEAR.bit=1,且引脚设置为输出,将相应的引脚置成低电平。
(4) GPxTOGGLE 触发寄存器
* GPxTOGGLE.bit=0,没有影响;
* GPxTOGGLE.bit=1,且引脚设置为输出,将相应的引脚取反。
因此,将引脚设置成高电平或低电平有3种不同方式。
(1) 数据寄存器方式:
在引脚已配置为输出的情况下,通过对单一GPxDAT 寄存器的设置,将对应引脚置成高电
平或低电平。
(2) 设置/清除寄存器方式:
在引脚已配置为输出的情况下,通过对GPxSET 及GPxCLEAR 两个寄存器的设置,将对应
引脚置成高电平或低电平。
(3) 触发寄存器方式:
在引脚已配置为输出的情况下,通过对GPxTOGGLE 寄存器的设置,将相应引脚的电平取
反。
这4类特殊寄存器不受EALLOW 保护,用户可正常访问。
*******************************************************************************************/
void Gpio_select(void)
{
Uint16 var1;
Uint16 var2;
Uint16 var3;
var1= 0x0000; // 设置 GPIO 多路器为I/O功能
var2= 0xFFFF; // 设置 GPIO 方向为输出
var3= 0x0000; // 设置输入量化值
EALLOW; // 允许访问受保护的空间
// 以下6条指令将GPIO引脚配置成I/O功能
GpioMuxRegs.GPAMUX.all=var1; // GPAMUX(GPIO A 功能选择控制寄存器)
// 将GPIO A所有16个端口配置为I/O功能.
// 若变量var1某位为1,则对应引脚配置
// 为外设功能 P617
GpioMuxRegs.GPBMUX.all=var1;
GpioMuxRegs.GPDMUX.all=var1;
GpioMuxRegs.GPFMUX.all=var1;
GpioMuxRegs.GPEMUX.all=var1;
GpioMuxRegs.GPGMUX.all=var1;
// 以下6条指令选择GPIO方向为输出
GpioMuxRegs.GPADIR.all=var2; // GPADIR(GPIO A 方向控制寄存器)
// 将GPIO A所有16个端口配置成数字量
// 输出.若变量var2某位为0,则对应引脚
// 配置成数字量输入 P618
GpioMuxRegs.GPBDIR.all=var2;
GpioMuxRegs.GPDDIR.all=var2;
GpioMuxRegs.GPEDIR.all=var2;
GpioMuxRegs.GPFDIR.all=var2;
GpioMuxRegs.GPGDIR.all=var2;
// 设置采样周期限制值
GpioMuxRegs.GPAQUAL.all=var3; // GPAQUAL(GPIO A 采样周期限制寄存器)
GpioMuxRegs.GPBQUAL.all=var3;
GpioMuxRegs.GPDQUAL.all=var3;
GpioMuxRegs.GPEQUAL.all=var3;
EDIS; // 禁止访问受保护的空间 }
/*******************************************************************************************
函数名称: delay_loop()
函数功能: 简单延时
输入参数: 无
输出参数: 无
*******************************************************************************************/
void delay_loop()
{
Uint32 i;
for (i = 0; i < 500000; i++) {} }
//================================================================================
// No more.
//================================================================================
实验3 SCI实验
一、SCI Autobaud 实验
文件: Example_281xSci_Autobaud_.c
标题: DSP281x SCI 自动波特探测示例 (DSP281x SCI Autobaud detect example)
提要: 这个示例需要DSP281x V1.00头文件支持,并且将这个项目配置成"boot to H0"方式。
测试需将以下硬件连接起来:
SCIATX <-> SCIBRX
SCIARX <-> SCIATX
在波特率变化的条件下,这个测试完成自动波特率的锁定。
要使这个测试完全运行,需将SCI-A引脚直接连接到SCI-B引脚,不必通过收发装置。
在高波特率情况下,输入数据位的回传率(波特率)将受到收发器及连接器的影响。在高波特率条件下,
这个回传率能可靠地进行自动波特率的检测。
SCIA: 从机,自动波特率锁定,接收字符并将这些字符返回给主机。采用RX中断接收字符。
SCIB: 主机,已知波特率,传送字符给从机并检测回送值。
采用中断方式,对不断地通过SCIA的数据进行内部回送测试。
观察变量: BRRVal - 用于SCIB的当前BRR值
ReceivedAChar - SCIA接收到的字符
ReceivedBChar - SCIB接收到的字符
SendChar - SCIB送出的字符
SciaRegs.SCILBAUD - 通过自动波特锁定对SCIA波特率寄存器设置
SciaRegs.SCIHBAUD
*******************************************************************************************/
#include "DSP281x_Device.h" // DSP281x Headerfile Include File
#include "DSP281x_Examples.h" // DSP281x Examples Include File
#define BAUDSTEP 100 // 在每个自动波特锁定之间BRR取增量。
// 在本文件之内建立的函数原型声明。
void scia_init(void);
void scib_init(void);
void scia_xmit(int a);
void scib_xmit(int a);
void scia_AutobaudLock(void);
void error(int);
interrupt void rxaint_isr(void); void LedD_Display(void);
void LedH_Display(void);
// 这个示例要用的全局计数器。
Uint16 LoopCount;
//Uint16 xmitCount;
Uint16 ReceivedCount;
Uint16 ErrorCount;
Uint16 SendChar;
Uint16 ReceivedAChar; // SCIA 接收字符
Uint16 ReceivedBChar; // SCIB 接收字符
Uint16 BRRVal;
Uint16 ErrorFlag;
Uint16 Buff[10] = {0x55, 0xAA, 0xF0, 0x0F, 0x00, 0xFF, 0xF5, 0x5F, 0xA5, 0x5A};
Uint16 count=0;
void main(void)
{
Uint16 i;
// 步骤1. 系统控制初始化: PLL,WatchDog,使能外设时钟。
// 这个示例函数由DSP281x_SysCtrl.c文件建立。
InitSysCtrl();
// 步骤2. GPIO初始化:
// 这个示例函数由DSP281x_Gpio.c文件建立,例举说明如何设置GPIO为其默认状态。
//InitGpio(); // 这个示例跳过这个函数。
EALLOW; // 允许访问受保护的寄存器。
GpioMuxRegs.GPFMUX.all=0x0030;
// F端口设置为:x000 0000 0011 0000,选择GPIO的SCIA引脚?
GpioMuxRegs.GPGMUX.all=0x0030;
// G端口设置为:x000 0000 0011 0000,选择GPIO的SCIB引脚。
EDIS;
// 初始化PIE控制寄存器为其默认状态:关PIE所有中断及清除标志位。
// 这个示例函数由DSP281x_PieCtrl.c文件建立,
InitPieCtrl();
// 关CPU中断及清除CPU所有中断标志位。
IER = 0x0000; // 关CPU中断。IER: 中断使能寄存器。
IFR = 0x0000; // 清除CPU中断标志位。IFR: 中断标志寄存器。
// 初始化PIE向量表,这张表指明中断服务程序(ISR)的整个架构。即使在这个示例中用不到中
// 断,仍然板上组装整个向量表。对调试而言,这是很有用的。
// ISR程序的整个架构由DSP281x_DefaultIsr.c文件建立。
InitPieVectTable(); // 这个函数在DSP281x_PieVect.c文件内建立。
// 在这个示例中用到的中断再映射到在本文件内建立的ISR函数中。
EALLOW; // 允许写入受保护的寄存器
//*******************************************************************************************
// 关于 "PieVectTable.RXAINT = &rxaint_isr;" 指令的说明
// 1. rxaint_isr 是一个关于SCI_A接收先进先出(FIFO)的中断服务程序(ISR)。 // 2. 这个中断程序响应中断扩展(PIE)向量表第9组第1个中断向量RXAINT的中断请求。 // 3. 为了使这个程序响应对应的中断,还需作如下配置:
// PieCtrlRegs.PIECRTL.bit.ENPIE = 1; // //使能PIE向量表。这条指令在在上面引用函数InitPieVectTable()中。 // PieCtrlRegs.PIEIER9.bit.INTx1=1; // // 使能PIE 第9组 INT1(RXAINT)中断。这条指令相当于后续指令: // // PieCtrlRegs.PIEIER9.all = 0x0001; // IER = 0x100;
// // 使能第9组中断。见后续指令。
// EINT;
// // 开放可屏蔽中断。 见后续指令。
// 4. 这样,在发生RXAINT中断的情况下,将执行rxaint_isr()中断服务程序。
// "PieVectTable.RXAINT = &rxaint_isr;" 指令实际上就是通知编译器,在发生RXAINT中断的情况下, // 将执行rxaint_isr()中断服务程序。rxaint_isr头上的"&"为取地址运算符。
//*******************************************************************************************
PieVectTable.RXAINT = &rxaint_isr;
EDIS; // 禁止写入受保护的寄存器
// 步骤4. 初始化器件所有外设:
// 这个函数在DSP281x_InitPeripherals.c文件内建立。
//InitPeripherals(); // 本例不需要。
scia_init(); // 初始化SCIA
scib_init(); // 初始化SCIB
// 步骤5. 用户特定代码,使能中断。
LoopCount = 0;
ErrorCount = 0;
// 使能中断。
PieCtrlRegs.PIEIER9.all = 0x0001; // 使能整个SCIA RXINT中断
IER |= 0x0100; // 使能PIEIER9及INT9
EINT; // 开放可屏蔽中断
// BRR初始值为1,通过BAUDSTEP对每一步波特率设置BRR增量。
for (BRRVal = 0x0000; BRRVal < (Uint32)0xFFFF; BRRVal+=BAUDSTEP)
{
// SCIB 为一个已知波特率,SCIA为与之匹配的自动波特。
ScibRegs.SCIHBAUD = (BRRVal >> 8);
// 取BRRVal移出低8位保留高8位的值,存入8位寄存器SCIHBAUD。
// BRRVal原值不变。
ScibRegs.SCILBAUD = (BRRVal);
// 将BRRVal低8位的值存入 8位寄存器SCILBAUD
scia_AutobaudLock(); // SCIA自动波特锁定子程序。
while(ScibRegs.SCIRXST.bit.RXRDY != 1) { }
// 当RXRDY=1时,说明SCIB接收到的数据从RXSHF寄存器已经移到接收缓冲器
// (SCIRXBUF),条件为假,跳过空循环体{ },执行其后的指令,否则等待。SCI接收状态
// 寄存器SCIRXST[6]为SCI接收器就绪标志位 RXRDY。当从SCIRXBUF寄存器中读一
// 个新的字节时,接收器将该位置1,此时,如果RX/BK INT ENA(SCICTL2.1)位=1,将
// 产生一个接收器中断。通过读SCIRXBUF寄存器,或者有效的SW RESET或者系统复
// 位可使RXRDY清0。
// 当RXRDY=0,SCIRXBUF中没有字符。
// 当RXRDY=1,准备从SCIRXBUF读字符。
ReceivedBChar = 0; // SCIB 接收字符置0。
ReceivedBChar = ScibRegs.SCIRXBUF.bit.RXDT;
// SCIB读取接收缓冲器(SCIRXBUF)中的数据。当读取SCIRXBUF,标志位RXRDY清0。
// 当前接收到的数据从RXSHF寄存器移到接收缓冲器时,标志位RXRDY置1,准备读取
// 数据。如果位RX/BK INT ENA(SCICTL2.1)置1,这种改变将产生一个中断。当读取
// SCIRXBUF,标志位复位。
// SCIRXBUF通过系统复位清除。
// SCIRXBUF[7:0]为接收字符位: RXDT7-RXDT0
if(ReceivedBChar != 'A') // SCIB读出的字符不为 A ,转出错处理。
{
error(0);
}
// Send/echoback characters 送出/返回字符
// 55 AA F0 0F 00 FF F5 5F A5 5A
for(i= 0; i<=9; i++)
{
SendChar = Buff[i]; // SCIB取出数组中的第i个字符
scib_xmit(SendChar);
// SCIB初始化中断并以中断方式传送数据。由于通过外部连线SCIATX <-> SCIBRX,
// SCIARX <-> SCIATX,因此,当SCIB发送数据时,SCIA接收数据;当SCIA发送数据时,
// SCIB接收数据。这里上下两条指令作用为:SCIB发出一个数据,然后等待SCIA接收这
// 个数据并返回一个数据。SCIA向SCIB回传的数据是其接收到的SCIB发出数据的反码。
// 等待获得返回的字符并检查是否与送出的相反。
while(ScibRegs.SCIRXST.bit.RXRDY != 1)
//见本节程序段前3条指令。
{
asm(" NOP");
}
ReceivedBChar = 0;
ReceivedBChar = ScibRegs.SCIRXBUF.bit.RXDT;
if(ReceivedBChar != SendChar) error(1);
}
} // Repeat for next BRR setting
// 对下一个BRR设置重复运行。
// Stop here, no more
for(;;)
{
asm(" NOP");
}
}
/* --------------------------------------------------- */
/* ISR for PIE INT9.1 */
/* Connected to RXAINT SCI-A */
/* ----------------------------------------------------*/
/*******************************************************************************************
函数: rxaint_isr(void)
功能: RXAINT 中断服务程序。在发生RXAINT中断的情况下,将执行以下中断服务程序。 *******************************************************************************************/
interrupt void rxaint_isr(void) // SCI-A {
// Insert ISR Code here
// 此处插入ISR代码
PieCtrlRegs.PIEACK.all = PIEACK_GROUP9;
// 在 DSP281x_PieCtrl.h 头文件中,PIEACK_GROUP9定义为0x0100
// 置PIE中断应答寄存器PIEACK[8]=1,应答RXAINT中断。
// 如果进行自动波特检测,须清除CDC。
if(SciaRegs.SCIFFCT.bit.CDC == 1)
// 在 scia_AutobaudLock() 程序中,已将CDC 置1(使能自动检测校准),
// 当CDC=1时,执行下面的程序,否则跳过。
{
SciaRegs.SCIFFCT.bit.ABDCLR = 1;
// SCI FIFO(SCI 先进先出)控制寄存器SCIFFCT[14]为 SCIFFCT[15] 自动波特率检测位ABD的
// 清除位 ABDCLR。
// 当 ABD=0,自动波特率检测未完成。'A''a'字符未接收到。
// 当 ABD=1,自动波特硬件在SCI接收寄存器中检测到'A''a'字符,自动检测完成。
// 当 ABDCLR=0,对ABD标志位没有影响。
// 当 ABDCLR=1,清除第15位ABD标志位。 P559
SciaRegs.SCIFFCT.bit.CDC = 0;
// 禁止自动波特检测校准。
// 检测接收到地字符-应该为A。
ReceivedAChar = 0;
ReceivedAChar = SciaRegs.SCIRXBUF.all;
// 将SCIA接收到的字符送赋给ReceivedAChar
if(ReceivedAChar != 'A')
// 不是'A'属错误2,终止仿真; 是'A',SCIA回传接收到的字符。
{
error(2);
}
else scia_xmit(ReceivedAChar);
}
// This was not autobaud detect
// 当CDC=0,即不进行波特自动检测校准,执行以下程序。
else
{
// 检测接收到的字符应与SCIB送出的字符相反(反码)。
ReceivedAChar = 0;
ReceivedAChar = SciaRegs.SCIRXBUF.all;
if(ReceivedAChar != SendChar)
{
error(3); //上电运行出现错误3,再编译可运行
}
else scia_xmit(ReceivedAChar);
}
SciaRegs.SCIFFRX.bit.RXFFINTCLR = 1; // clear Receive interrupt flag
ReceivedCount++;
}
void error(int ErrorFlag)
{
ErrorCount++;
asm(" ESTOP0"); // Uncomment to stop the test here
for (;;);
}
// SCIA 8-bit word, baud rate 0x000F, default, 1 STOP bit, no parity
void scia_init()
{
// Note: Clocks were turned on to the SCIA peripheral
// in the InitSysCtrl() function
// Reset FIFO's
SciaRegs.SCIFFTX.all=0x8000;
// SCI FIFO 发送寄存器SCIFFTX[15]为复位位SCIRST。
// 当SCIRST=0,复位SCI发送和接收通道。SCI FIFO寄存器配置位继续保持原有状态。
// 当SCIRST=1,SCI FIFO重新开始和接收。
SciaRegs.SCICCR.all =0x0007;
// 对SCI通信控制寄存器(SCICCR)进行配置。一个结束位,禁止回送, 禁止极性功能,
// 8位字符,异步方式,选择空闲线协议。
SciaRegs.SCICTL1.all =0x0003;
// 使能TX, RX, 内部SCICLK,禁止接收错误中断,禁止睡眠,禁止TXWAKE
SciaRegs.SCICTL2.all =0x0003;
// 使能RXRDY/BRKDT中断,使能TXRDY中断。
SciaRegs.SCICTL2.bit.RXBKINTENA =1;
// 使能RXRDY/BRKDT中断。 与上面一条指令重复。
SciaRegs.SCICTL1.all =0x0023; // Relinquish SCI from Reset
// SCICTL1[5]=SW REST=1,放弃SCI复位;
// SCICTL1[1]=TXENA=1,启动发送;
// SCICTL1[0]=RXENA=1,将接收到的字符传送到SCIRXBUF和SCIRXEMU }
// SCIB 8-bit word, baud rate 0x000F, default, 1 STOP bit, no parity
void scib_init()
{
// Reset FIFO's
ScibRegs.SCIFFTX.all=0x8000; // SCIRST=1.
// SCI FIFO 发送寄存器SCIFFTX[15]为复位位SCIRST。
// 当SCIRST=0,复位SCIB发送和接收通道。SCIB FIFO寄存器配置位继续保持原有状态。
// 当SCIRST=1,SCIB FIFO重新开始和接收。
ScibRegs.SCICCR.all =0x0007;
// 对SCI通信控制寄存器(SCICCR)进行配置。一个结束位,禁止回送, 禁止极性功能,
// 8位字符,异步方式,选择空闲线协议。
ScibRegs.SCICTL1.all =0x0003;
// 使能TX, RX, 内部SCICLK,禁止接收错误中断,禁止睡眠,禁止TXWAKE
// Disable RxErr, Sleep, TX Wake,
// Diable Rx Interrupt, Tx Interrupt
ScibRegs.SCICTL2.all = 0x0000;
// Relinquish SCI-A from reset
ScibRegs.SCICTL1.all = 0x0023;
return;
}
/*******************************************************************************************
函数: scia_xmit(int a)
功能: 从SCIA发送一个字符
*******************************************************************************************/
void scia_xmit(int a)
{
if(count>9999) count=0;
count++;
SciaRegs.SCITXBUF=a;
// SCI 发送数据缓冲寄存器。要发送的数据写入SCITXBUF。必须右靠齐,因为长度大于8个位的
// 字符最左边的位被忽略。将数据从该寄存器传送到 TXSHF发送移位寄存器的操作,使得TXRDY
// 标志(SCICTL2.7)置1,表示SCITXBUF准备接收下一个数据列。如果TXINTENA(SCICTL2.0)位=1,
// 该数据的发送会产生一个中断。
}
/*******************************************************************************************
函数: scib_xmit(int a)
功能: 从SCIB发送一个字符
*******************************************************************************************/
void scib_xmit(int a)
{
if(count>9999) count=0;
count++;
ScibRegs.SCITXBUF=a;
// SCI 发送数据缓冲寄存器。要发送的数据写入SCITXBUF。必须右靠齐,因为长度大于8个位的
// 字符最左边的位被忽略。将数据从该寄存器传送到 TXSHF发送移位寄存器的操作,使得TXRDY
// 标志(SCICTL2.7)置1,表示SCITXBUF准备接收下一个数据列。如果TXINTENA(SCICTL2.0)位=1,
// 该数据的发送会产生一个中断。
}
/*******************************************************************************************
函数: scia_AutobaudLock()
功能: 完成对主机的自动波特率锁定
注意: 如果自动波特一直未出现,则运行程序将在这段程序悬挂起来,好比机械装置
不能暂停一样。???
// Perform autobaud lock with the host.
// Note that if autobaud never occurs the program will hang in this routine
// as there is no timeout mechanism included. *******************************************************************************************/
void scia_AutobaudLock()
{
Uint32 i;
SciaRegs.SCICTL1.bit.SWRESET = 0;
// SCI 控制寄存器1 SCICTL1[5]为SCI软件复位位SWRESET。
// 当 SWRESET=0,对SCI状态机和操作标志初始化到复位条件,该位对任何配置位都不起作
// 用。
// 当 SWRESET=1,系统复位后,写入1可重启SCI。 P549
SciaRegs.SCICTL1.bit.SWRESET = 1;
// Must prime baud register with >= 1
// 波特率寄存器初始值必须大于等于1。 P551
SciaRegs.SCILBAUD = 1;
// Prepare for autobaud detection
// Make sure the ABD bit is clear by writing a 1 to ABDCLR
// Set the CDC bit to enable autobaud detection
// 准备自动波特率探测。确定ABD位通过向ABDCLR写1已被清除,设置CDC位使能自动波
// 特率探测。
SciaRegs.SCIFFCT.bit.ABDCLR = 1;
// SCI FIFO(SCI 先进先出)控制寄存器SCIFFCT[14]为 SCIFFCT[15] 自动波特率检测位ABD的
// 清除位 ABDCLR。
// 当 ABD=0,自动波特率检测未完成。'A''a'字符未接收到。
// 当 ABD=1,自动波特硬件在SCI接收寄存器中检测到'A''a'字符,自动检测完成。
// 当 ABDCLR=0,对ABD标志位没有影响。
// 当 ABDCLR=1,清除第15位ABD标志位。 P559
SciaRegs.SCIFFCT.bit.CDC = 1;
// SCI FIFO(SCI 先进先出)控制寄存器SCIFFCT[13]为 CDC自动校准检测位CDC
// 当CDC=0,禁止自动检测校准。
// 当CDC=1,使能自动检测校准。
// Wait until we correctly read an 'A' or 'a' and lock
// 一直等待到可正确地读出一个 'A' or 'a' 并且锁住。
while(SciaRegs.SCIFFCT.bit.CDC == 1)
{
// Note the lower the baud rate the longer
// this delay has to be
// 注意: 较低的波特率需较长的延时。
//for(i = 1; i<= 0x0FFFFFF; i++)
for(i = 1; i<= 0x0FFFF; i++)
{
asm(" NOP");
} // delay 延时
LedD_Display();
LedH_Display();
if(SciaRegs.SCIFFCT.bit.CDC == 1) scib_xmit('A');
}
return;
}
//================================================================================
// No more.
//================================================================================
二、Sci_FFDLoopBack实验
文件: Sci_FFDLoopBack.c
标题: DSP281x器件SCI先进先出(SCI FIFO)数字回送测试
条件: 该程序需DSP281x V1.00头文件支持,并将其配置为"boot to H0"操作方式。除了boot方式配置之
外,不需要其它的硬件配置。
说明: 这个测试程序用到SCI模块回送测试方式。发送一组中文字符串。通过SCI的回送功能,将发的字
符与接收到的字符进行比较,不相等终止仿真。
另外在以下两个方面对TI提供的驱动源码进行了硬件和软件的增强:
(1) 增加了与PC机连接的RS232硬件接口。这样,在通信正常时,超级终端会不断地刷新显示:
"夫君子之行,静以修身俭以养德,非澹泊无以明志,非宁静无以致远。<<诸葛亮 诫子书>>"。
(2) 增加了LED数码管显示的硬件接口。以便将串行通信的次数反映在LED数码管上。 以下两个变量可以通过打开CCS视窗进行观察:
LoopCount 送出字符数
ErrorCount 错误次数
********************************************************************************************
#include "DSP281x_Device.h"
#include "DSP281x_Examples.h"
// 本文件中建立的原型函数声明
void scib_init(void); // SCI_B 初始化
void scib_fifo_init(void); // SCIB FIFO 先进先出初始化
void scib_xmit(int a); // 从SCIB发送一个字符
void error(int); // 数据传送出现错误,终止仿真。
// 外部LED显示函数声明
void LedD_Display(void);
// 将SCI通信次数以10进制形式,在Led第4,3,2,1位数码管上进行显示 void LedH_Display(void);
// 将SCI通信次数以16进制形式,在Led第8,7,6,5位数码管上进行显示 char St[] = " 夫君子之行,静以修身俭以养德,非澹泊无以明志,非宁静无以致远。<<诸葛亮 诫子书>>\n\r\0 ";
// "\n"为换行符,"\0" 为字符串结束符,"\r" 为回车符, "\t" 为横向跳格符,相当于Tab键,"\v" 为竖向
// 跳格符,"\b" 为退格符, "\f" 为走纸换页符,本例中用到的全局变量
Uint16 count=0; // 串行通信次数计数器
Uint16 SendChar; // 发送字符
Uint16 ReceivedChar; // 接收字符
Uint16 ErrorCount=0; // 出错次数计数器
void main(void)
{
Uint16 i=0xffff;
// 步骤1. 系统控制初始化: PLL, WatchDog, 使能外设时钟。
// 这个示例函数在DSP281x_SysCtrl.c文件中建立
InitSysCtrl();
// 步骤2. 根据器件或者特殊应用选择GPIO: 这个函数由DSP281x_Gpio.c文件建立。
//InitGpio(); // 跳过这个函数,该示例文件仅选择SCI的I/0口
EALLOW; // 允许访问受保护的寄存器
//GpioMuxRegs.GPFMUX.all=0x0030;
// 选择GPIO作为SCI引脚,F端口多路器设置为: x000 00000011 0000
GpioMuxRegs.GPGMUX.bit.SCITXDB_GPIOG4 = 1;
// 将GPIOG4引脚配置成SCITXDB外设功能。这里采用TXB口通信
EDIS; // 禁止访问受保护的寄存器
// 步骤3. 初始化PIE向量表:
// 初始化PIE向量表,该向量表指明了中断服务程序(ISR)的一种构架。这一架构
// 程序(壳程序)在DSP281x_DefaultIsr.c文件中建立。可以在DSP281x_DefaultIsr.c文件
// 中适当的壳ISR处插入用户特殊的ISR代码。
DINT;
IER = 0x0000; // 关CPU中断。、IER: 中断使能寄存器。
IFR = 0x0000; // 清除CPU中断标志位。 IFR: 中断标志寄存器。
//InitPieCtrl(); // 初始化PIE控制寄存器为默认状态。这个函数在DSP281x_PieCtrl.c
// 文中件建立。本例不用PIE。
InitPieVectTable();
// 初始化PIE向量表为已知状态。这个函数在DSP281x_PieVect.c
// 文件中建立。
// 该函数板上组装了PIE向量表,这个向量表指明由
// DSP281x_DefaultIsr.c
// 文件建立的中断服务程序(ISR)的一种构架。
EnableInterrupts(); // 使能CPU及PIE中断。该函数在DSP281x_PieCtrl.c文件中建立。
// 步骤4. 初始化器件外设为已知状态: 该函数在DSP281x_InitPeripherals.c文件中// 建立。
// InitPeripherals(); // 对SCI检测而言,可跳过这个函数。
// 步骤5. 用户函数,再分配可选择的向量,使能中断:
scib_fifo_init(); // 初始化SCI FIFO
scib_init(); // SCIB初始化
// 注意: 这个示例不需要自动波特率锁定。
// 步骤6. 无休止的发送同一个St[]字符串。
/*******************************************************************************************
for(;;)之后的循环体将无限循环。无休止的发送同一个St[]字符串。
*******************************************************************************************/
for(;;) // 无休止地执行循环体,相当于while(1)语句。用这一无限循环语句
// 编译器不会发出编译警告。用while(1)出现警告。
{
for(i=0;St[i]!='\0';i++) //每次发送一个字符,连续发送一个字符串。
// 取出字符串St[]中的第i个元素,若该元素不等于'\0',表示字符串
// 元素未发送完,则继续发送,若等于'\0,表示字符串元素发送完毕。
{
scib_xmit(St[i]); // 发送字符串St[]中的第i个字符。
while(ScibRegs.SCIFFRX.bit.RXFIFST !=1) { }
// SCI FIFO接收寄存器SCIFFRX[12:8]为接收字符个数状态位RXFIFST。
// 它是一个5位值。表示已接收字符的个数,其最大值为10000b,对应
// 接收FIFO中有16个字符,0xxxx表示有X个字符。由于采用了内部
// 回送方式,因此,当发送FIFO中有1个字符(本例每次只发一个字符)
// 时,接收FIFO也为一个字符。这条指令用于判断RXFIFST的位值是
// 否为1,不为1等待,为1表示已接收到一个字符,程序跳转执行。
ReceivedChar = ScibRegs.SCIRXBUF.all; // 检查接收到的字符。
// 在回送方式中,接收数据缓冲寄存器SCIRXBUF存放发送的数据,用
// 于检查发送数据是否出问题。将内回送接收的数据赋给ReceivedChar
if(ReceivedChar != St[i]) error(1);
// 判别发送与接收的字符数据是否相等,不等终止仿真。
}
if(count>9999) count=0;
count++;
LedD_Display(); // 在4个数码管上以十进制显示count
LedH_Display(); // 在另外4个数码管上以十六进制显示count
}
}
// 步骤7. 以下插入局部中断服务程序(ISRs)及有关函数:
/*******************************************************************************************
函数: scib_init()
功能: SCI_B 初始化
注意: DSP281x_SysCtrl.c文件中的锁相环函数InitPll(0x5)的实参原值为0xA,现改为0x5。
在外接晶振30MHz的条件下,当锁相环函数实参为0xA时,系统时钟由公式7-3确定。系统时钟:
SYSCLKOUT=(OSCCLK*DIV)/2=(30*5)/2=75.5MHz, 当锁相环函数实参为0x5时。低速外设时钟
与系统时钟SYSCLKOUT的关系由公式7-1确定。7-1式中的LSPCLK=2,采用默认值。故低速外
设时钟 LSPCLK=75.5/4=18.875 MHz
*******************************************************************************************/
void scib_init()
{
ScibRegs.SCICCR.all =0x0007;
// 对SCI通信控制寄存器(SCICCR)进行配置。一个结束位,禁止回送, 禁止极性功能,
//8位字符,异步方式,选择空闲线协议。
ScibRegs.SCICTL1.all =0x0003;
// 使能TX, RX, 内部SCICLK, 禁止接收错误中断,禁止睡眠,禁止TXWAKE
ScibRegs.SCICTL2.all =0x0003;
// 启动RXRDY/BRKDT中断,使能SCITXBUF中断
// ScibRegs.SCICTL2.bit.TXINTENA =1;
// 使能SCITXBUF中断,表示SCITXBUF寄存器准备接收下一个字符。
// 与上面一条指令重复,可删。
ScibRegs.SCICTL2.bit.RXBKINTENA =1;
// 启动接收缓冲器/中断。该位对SCI接收状态寄存器(SCIRXST)的RXRDY和BRKDT
// 标志(SCIRXST.6及.5位)位进行控制
ScibRegs.SCIHBAUD =0x0000; // 低速外设时钟为18.875 MHz,波特率为9600
// SCIHBAUD: 波特率选择最高有效字节寄存器
ScibRegs.SCILBAUD =0x00f5; // 低速外设时钟为18.875 MHz,波特率为9600
// SCILBAUD: 波特率选择最低有效字节寄存器
// 注意:
// 波特率选择寄存器组设置为0x01E7,可产生9600波特率,必须满足如下条件:
// (1) 锁相环函数实参取值 0xA;
// (2) 低速外设时钟预定标(LOSPCP)寄存器取默认值 2。
// 当相环函数实参取值改为 0x5,LOSPCP取默认值 2,仍要产生9600波特率,则波特率
// 选择寄存器组设置值相应改为0x00f5。参见公式7-5。
ScibRegs.SCICCR.bit.LOOPBKENA =1; // 启动回送测试功能
ScibRegs.SCICTL1.all =0x0023; // Relinquish SCI from Reset
// SCICTL1[5]=SW REST=1,放弃SCI复位;
// SCICTL1[1]=TXENA=1,启动发送;
// SCICTL1[0]=RXENA=1,将接收到的字符传送到SCIRXBUF和SCIRXEMU }
/*******************************************************************************************
函数: void error()
功能: 数据传送出现错误,终止仿真。
*******************************************************************************************/
void error(int ErrorFlag)
{
ErrorCount++;
// asm(" ESTOP0"); // 不要注释符测试停在此处。
//for (;;);
}
/*******************************************************************************************
函数: scib_xmit(int a)
功? 从SCIB发送一个字符
*******************************************************************************************/
void scib_xmit(int a)
{ ScibRegs.SCITXBUF=a; }
/*******************************************************************************************
函数: scib_fifo_init()
功能: SCIB先进先出初始化
*******************************************************************************************/
void scib_fifo_init()
{
ScibRegs.SCIFFTX.all=0xE040;
// SCI FIFO 发送寄存器(SCIFFTX)
// SCIFFTX[15] = SCIRST(最高位)=1,SCI FIFO重新开始发送和接收。
// SCIFFTX[14] = SCIFFENA=1,使能SCI FIFO的增强型功能。
// SCIFFTX[13] = TXFIFO Reset=1,重新使能接收FIFO的操作。
// SCIFFTX[6] = TXFFINT CLR=1,清除第7位的标志位TXFFINT,即不产生TXFIFO中断。
ScibRegs.SCIFFRX.all=0x204f;
// SCI FIFO 接收寄存器(SCIFFRX)
// SCIFFRX[13] = RXFIFO Reset=1,重新使能接收FIFO的操作。
// SCIFFRX[6] = RXFFINT CLR=1,清除第7位的标志位RXFFINT,即不产生RXFIFO中断。
// SCIFFRX[3:0] = RXFFIL3-RXFFIL0=1111b,
ScibRegs.SCIFFCT.all=0x0;
// 禁止自动波特率校验,0延迟。
}
//================================================================================
// No more.
//================================================================================
三、Sci_LoopBack_Interrupts实验
文件: Sci_LoopBack_Interrupts.c
标题: 通过中断进行DSP281x器件SCI FIFO数字回送测试
条件: 该程序需DSP281x V1.00头文件支持,并将其配置为"boot to H0"操作方式,除了boot方式配置
之外,不需要其它的硬件配置。
说明: 这个程序是一个采用中断和SCI FIFOs两种方式,通过外设内部回送的关于SCI的一个示例。送
出一组数据流然后与接收到的数据流进行比较。 另外通过RS232接口将数据流发送给PC机。
另外在以下三个方面对TI提供的驱动源码进行了硬件和软件的增强:
(1) 增加了与PC机连接的RS232硬件接口。这样,在通信正常时,串口调试助手会周而复始地
刷新显示如下列出的SCI-B数据流。
(2) 增加了LED数码管显示的硬件接口。以便将串行通信的次数反映在LED数码管上。
(3) 增加了液晶屏显示硬件接口,用于刷新显示SCI-B接收的数据流(SCI-B TXD发送,SCI-B RXD
接收。
SCI-A发送如此一组数据: 00 01 02 03 04 05 06 07
01 02 03 04 05 06 07 08
02 03 04 05 06 07 08 09
....
FE FF 00 01 02 03 04 05
FF 00 01 02 03 04 05 06
etc..
SCI-B发送如此一组数据: FF FE FD FC FB FA F9 F8
FE FD FC FB FA F9 F8 F7
FD FC FB FA F9 F8 F7 F6
....
01 00 FF FE FD FC FB FA
00 FF FE FD FC FB FA F9
etc..
两组方式一直重复。
以下变量可以通过打开CCS视窗进行观察:
SCI-A SCI-B
sdataA sdataB 发送数据
rdataA rdataB 接收数据
rdata_pointA rdata_pointB 数据流中的跟踪节点,用于检查接收的数据 ********************************************************************************************
#include "DSP281x_Device.h" // DSP281x 头文件包含文件。 #include "DSP281x_Examples.h" // DSP281x 示例包含文件。 #define CPU_FREQ 150E6 // 编译器认可的一种数字定义方式。定义
// CPU_FREQ=150 000 000 。 #define SCI_FREQ 100E3 // 定义 SCI_FREQ=100 000。 #define SCI_PRD CPU_FREQ/(SCI_FREQ*8) //= 187
//本文件建立的函数原型声明。
interrupt void sciaTxFifoIsr(void); // SCIA发送先进先出中断函数。 interrupt void sciaRxFifoIsr(void); // SCIA接收先进先出中断函数。 interrupt void scibTxFifoIsr(void); // SCIB发送先进先出中断函数。 interrupt void scibRxFifoIsr(void); // SCIB接收先进先出中断函数。 void scia_fifo_init(void); // SCIA先进先出初始化函数。 void scib_fifo_init(void); // SCIB先进先出初始化函数。 void error(void); // 通信出错处理函数。
void delay(Uint16 dly);
void WriteXram(Uint16 *StartAddr, Uint16 *EndAddr);
void LedD_Display(void);
// 将SCI通信次数以10进制形式,在Led第4,3,2,1位数码管上进行显示(右边数) void LedH_Display(void);
// 将SCI通信次数以16进制形式,在Led第8,7,6,5位数码管上进行显示全局变量 Uint16 count=0; // 计数器,记录循环体循环的次数。 Uint16 sdataA[8]; // SCI-A发送数据
Uint16 sdataB[8]; // SCI-B发送数据
Uint16 rdataA[8]; // SCI-A接收数据
Uint16 rdataB[8]; // SCI-B接收数据
Uint16 rdata_pointA; // 用于检查接收的数据
Uint16 rdata_pointB;
Uint16 *Xaddr=(Uint16 *)0x13f000;
// 指针变量定义。外存地址0x13f000为McBSP回送数据存入的首地址 Uint16 Xaddr_track=0;
// 外存地址跟踪指针
void main(void)
{
Uint16 i;
// 步骤1. 系统控制初始化: PLL, WatchDog, 使能外设时钟。
// 这个示例函数在DSP281x_SysCtrl.c文件中建立
InitSysCtrl();
// 步骤2. 初始化GPIO: 这个示例函数在DSP281x_Gpio.c文件中建立,阐明如何将GPIO
// 设置成其默认状态。本例跳过这个函数.
//InitGpio();
lcd_init(); // Lcd 初始化。
clearscr1(); // 清除第一显示缓冲区:0x0000-0x29ff。
clearscr2(); // 清除第二显示缓冲区:0x2a00-0x53ff。
clearscr3(); // 清除第三显示缓冲区:0x5400-0x7FFF。
Disp_XramTab(); // 液晶屏界面显示。
// 仅将GP I/O 设置成SCI-A 及 SCI-B 功能
EALLOW; // 允许访问受保护的寄存器。
//GpioMuxRegs.GPFMUX.bit.SCITXDA_GPIOF4 = 1;
// 将GPIOF4引脚配置成SCITXDA外设功能
//GpioMuxRegs.GPFMUX.bit.SCIRXDA_GPIOF5 = 1;
// 将GPIOF5引脚配置成SCIRXDA外设功能
GpioMuxRegs.GPFMUX.all = 0x0030; // 可用这条指令取代上面两条指令
//GpioMuxRegs.GPGMUX.bit.SCITXDB_GPIOG4 = 1;
// 将GPIOG4引脚配置成SCITXDB外设功能
//GpioMuxRegs.GPGMUX.bit.SCIRXDB_GPIOG5 = 1;
// 将GPIOG5引脚配置成SCIRXDB外设功能
GpioMuxRegs.GPGMUX.all = 0x0030; // 可用这条指令取代上面两条指令
EDIS; // 禁止访问受保护的寄存器。
// 步骤3. 清除所有中断和初始化PIE向量标
DINT; // 关CPU中断
InitPieCtrl();
// 将PIE控制寄存器初始化为其默认状态。这个默认状态就是关所有
// PIE中断及清除所有标志位。该函数由DSP281x_PieCtrl.c文件建立
IER = 0x0000; // 关CPU中断。 ( IER: 中断使能寄存器。)
IFR = 0x0000; // 清除CPU中断标志位。 ( IFR: 中断标志寄存器。)
InitPieVectTable();
// 初始化PIE向量表,该向量表指明了中断服务程序(ISR)的一种构架。
// 即使在这个示例中用不到中断,仍板上组装了整个PIE向量表。作为调试目的这是
// 很有用的。ISR程序架构由DSP281x_DefaultIsr.c文件建立。
// InitPieVectTable()函数由DSP281x_PieVect.c文件建立。
EALLOW; // 允许写入受保护的寄存器
// 用于这个示例的中断重新映射到由本文件建立的ISR函数
//*******************************************************************************************
// 关于 "PieVectTable.RXAINT = &sciaRxFifoIsr;" 指令的说明
// 1. sciaRxFifoIsr 是一个关于SCI_A接收先进先出(FIFO)的中断服务程序(ISR)。 // 2. 这个中断程序与中断扩展(PIE)向量表第9组第1个中断向量RXAINT对应。 // 3. 为了使这个程序响应对应的中断,还需作如下配置:
// PieCtrlRegs.PIECRTL.bit.ENPIE = 1; // //使能PIE向量表。这条指令在在上面引用函数InitPieVectTable()中。
// PieCtrlRegs.PIEIER9.bit.INTx1=1; // 使能PIE 第9组 INT1(RXAINT)中断 // IER = 0x100; // 使能第9组中断
// EINT; // 开放可屏蔽中断
// // 这几条指令在本程序的后续指令中可以找到。 // 4. 这样,在发生RXAINT中断的情况下,将执行sciaRxFifoIsr()中断服务程序。"PieVectTable.RXAINT =
// &sciaRxFifoIsr;" 指令实际上就是通知编译器,在发生RXAINT中断的情况下,将执行sciaRxFifoIsr()
// 中断服务程序。sciaRxFifoIsr头上的"&"为取地址运算符。
//*******************************************************************************************
PieVectTable.RXAINT = &sciaRxFifoIsr;
// PieVectTable 是一个外设中断扩展(PIE)向量表。它支持96个不同的中断,并把这些
// 中断分成12个组,
// RXAINT位于第9组中的第1个,TXAINT位于第9组中的第2个,
// RXBINT位于第9组中的第3个,TXBINT位于第9组中的第4个。
PieVectTable.TXAINT = &sciaTxFifoIsr;
PieVectTable.RXBINT = &scibRxFifoIsr;
PieVectTable.TXBINT = &scibTxFifoIsr;
EDIS; // 禁止写入受保护的寄存器
// 步骤4. 初始化所有外设器件:
//InitPeripherals(); // 这个函数由DSP281x_InitPeripherals.c文件建立。
// 本例跳过这个函数。
scia_fifo_init(); // Init SCI-A 初始化SCI-A
scib_fifo_init(); // Init SCI-B 初始化SCI-B
// 步骤5. 用户绝对代码,使能中断。
// 发送数据初始化。在每次传送数据之后,该数据将更新为下一个要传送的数据。
for(i = 0; i<8; i++) { sdataA[i] = i; }
// sdataA[0]=0,sdataA[1]=1,... sdataA[7]=7。
for(i = 0; i<8; i++) { sdataB[i] = 0xFF - i;}
// sdataB[0]=0xff,sdataB[1]=0xfe,... sdataB[7]=0xf8。
rdata_pointA = sdataA[0]; // rdata_pointA是一个动态变量,指向发送数组A
//sdataA[]中的第一个元素。
rdata_pointB = sdataB[0]; // rdata_pointB是一个动态变量,指向发送数组B
// sdataB[]中的第一个元素。这两个变量用于内部回送测试。
/********* 使能本示例所需的中断 **********/
PieCtrlRegs.PIECRTL.bit.ENPIE = 1; // 使能PIE向量表
PieCtrlRegs.PIEIER9.bit.INTx1=1; // 使能PIE 第9组 INT1(RXAINT)中断
PieCtrlRegs.PIEIER9.bit.INTx2=1; // 使能PIE 第9组 INT2(TXAINT)中断
PieCtrlRegs.PIEIER9.bit.INTx3=1; // 使能PIE 第9组 INT3(RXBINT)中断
PieCtrlRegs.PIEIER9.bit.INTx4=1; // 使能PIE 第9组 INT4(TXBINT)中断
IER = 0x100; // 使能第9组中断
EINT; // 开放可屏蔽中断
// 步骤6. 无限循环。
for(;;) //while(1) 循环体无限循环,若用while(1),编译器会发出警告。
{
if(count>9999) count=0;
else
count++;
LedH_Display();
LedD_Display();
//DispXram_D((Uint16 *)0x13f000);
// 在液晶屏上以10进制显示存储区0x13f000-0x13f02b中的一块数据。
DispXram_H((Uint16 *)0x13f000);
// 在液晶屏上以16进制显示存储区0x13f000-0x13f02b中的一块数据。
delay(100);
}
}
void error(void)
{
asm(" ESTOP0"); // 测试出错,终止。 C语言中插入汇编指令的格
// 式: asm(" ESTOP0");意为 仿真停止
// 0(ESTOP0)。第一个双引号与指令之间要空格。
for (;;); // 无限空循环。
}
//*******************************************************************************************
// 函数: sciaTxFifoIsr
// 标题: SCI_A 发送先进先出(FIFO)中断服务子程序(ISR)
//*******************************************************************************************
interrupt void sciaTxFifoIsr(void) {
Uint16 i;
for(i=0; i< 8; i++) { SciaRegs.SCITXBUF=sdataA[i]; }
// 将发送数组A第i个数据sdataA[i]放入发送缓冲器SCITXBUF,发送8个数据
for(i=0; i< 8; i++) // 下一个周期,发送数据取增量。
{
sdataA[i] = (sdataA[i]+1) & 0x00FF;
// 这里有2个sdataA[i],后一个sdataA[i]是从先皊dataA[]数组中取
// 第i个元素,在加1并屏蔽高8位后重新赋值给第i个元素。
// 假如先前一个数组的8个元素为: 2,3,4,5,6,7,8,9
// 则后一个数组的8个元素为: 3,4,5,6,7,8,9,10...
}
SciaRegs.SCIFFTX.bit.TXINTCLR=1; // SCIFFTX[6]为TXINTCLR位,该位置1
// 清除SCI中断标志位TXFFIN
PieCtrlRegs.PIEACK.all |= 0x100; // 发出PIE应答,以示响应INT9中断 }
//*******************************************************************************************
// 函数: sciaRxFifoIsr()
// 标题: SCI_A 接收先进先出(FIFO)中断服务子程序(ISR)
//*******************************************************************************************
interrupt void sciaRxFifoIsr(void)
{
Uint16 i;
for(i=0;i<8;i++) { rdataA[i]=SciaRegs.SCIRXBUF.all; }
// 读出接收缓冲器SCIRXBUF中数据,放入接收数组第i位,读出8个数据
for(i=0;i<8;i++) // 检查接收的数据
{
if(rdataA[i] != ( (rdata_pointA+i) & 0x00FF) ) error();
// 检测rdataA[i]与rdata_pointA+i对应8个数据相等否,不等转出错处理出,终止仿真调试;
// 相等顺执。
// 由于rdata_pointA 跟踪发送数组A sdataA[]中的第一个元素,因此(rdata_pointA+i)即为发
// 送数组的对应元素。
// 接收数组第i个元素rdataA[i]为发送数组A sdataA[]中的第i个元素,rdataA[i]与
// (rdata_pointA+i)两者相等,传送无误,否则出错。
// 这里用到DSP281x串行传送的内部回送功能。
}
rdata_pointA = (rdata_pointA+1) & 0x00FF; // 指向下一次发送数组第一个元素
SciaRegs.SCIFFRX.bit.RXFFOVRCLR=1; // 清除溢出标志位
SciaRegs.SCIFFRX.bit.RXFFINTCLR=1; // 清除中断标志位
PieCtrlRegs.PIEACK.all|=0x100; // 发出PIE应答,以示响应INT9中断
// PIEACK与0x100按位或后再对PIEACK赋值 }
//*******************************************************************************************
// 函数: scia_fifo_init():
// 功能: SCI_A 先进先出(FIFO)初始化子程序
// 注意: DSP281x_SysCtrl.c文件中的锁相环函数InitPll(0x5)的实参原值为0xA,现改为0x5。 // 在外接晶振30MHz的条件下,当锁相环函数实参为0xA时,系统时钟
// SYSCLKOUT=(OSCCLK*DIV)/2=(30*10)/2=150MHz // 当锁相环函数实参为0x5时,系统时钟
// SYSCLKOUT=(OSCCLK*DIV)/2=(30*5)/2=75.5MHz // 低速外设时钟与系统时钟SYSCLKOUT的关系参见公式7-1。本函数采用低速外设时钟预定 // 标(LOSPCP)寄存器的默认值(默认值为2)。故低速外设时钟
// LSPCLK=75.5/4=18.875 MHz
//*******************************************************************************************
void scia_fifo_init()
{
SciaRegs.SCICCR.all =0x0007;
// 对SCI通信控制寄存器(SCICCR)进行配置。一个结束位,禁止回送,
// 禁止极性功能,8位字符,异步方式,选择空闲线协议。
SciaRegs.SCICTL1.all =0x0003;
// 使能TX, RX, 内部SCICLK,禁止接收错误中断,禁止睡眠,禁止TXWAKE
SciaRegs.SCICTL2.bit.TXINTENA =1;
// SCITXBUF中断使能,表示SCITXBUF寄存器准备接收下一个字符。
SciaRegs.SCICTL2.bit.RXBKINTENA =1;
// 启动接收缓冲器/中断。该位对SCI接收状态寄存器(SCIRXST)的RXRDY和
// BRKDT标志(SCIRXST.6及.5位)位进行控制
ScibRegs.SCIHBAUD =0x0000;//=0x0001;
// SCIHBAUD: 波特率选择最高有效字节寄存器
ScibRegs.SCILBAUD =0x00f5;//=0x00E7;
// SCILBAUD: 波特率选择最低有效字节寄存器
// 注意:
// 这里的波特率选择寄存器组设置为0x01E7,可产生9600波特率,须满足如下条件:
// (1) 锁相环函数实参取值 0xA;
// (2) 低速外设时钟预定标(LOSPCP)寄存器取默认值 2。
// 若锁相环函数实参取值改为 0x5,则波特率选择寄存器组设置值相应改为0x00f5。
SciaRegs.SCICCR.bit.LOOPBKENA =1; // 启动回送测试功能
SciaRegs.SCIFFTX.all=0xC028; // SCI FIFO 发送寄存器(SCIFFTX)
// SCI FIFO重新开始和接收,使能
// SCI FIFO的增强型功能
// 使能匹配中断,FIFO级位为8
SciaRegs.SCIFFRX.all=0x0028; // 使能匹配中断,FIFO级位为8
//SciaRegs.SCIFFCT.all=0x00; // SCI FIFO 控制寄存器(SCIFFCT)
SciaRegs.SCICTL1.all =0x0023; // Relinquish SCI from Reset
SciaRegs.SCIFFTX.bit.TXFIFOXRESET=1;
SciaRegs.SCIFFRX.bit.RXFIFORESET=1; }
//*******************************************************************************************
// 函数: scibTxFifoIsr
// 标题: SCI_B 发送先进先出(FIFO)中断服务子程序(ISR)
//*******************************************************************************************
interrupt void scibTxFifoIsr(void)
{
Uint16 i;
for(i=0; i< 8; i++) { ScibRegs.SCITXBUF=sdataB[i]; }
// 将发送数组B第i个数据sdataB[i]放入发送缓冲器SCITXBUF,发送8个数据
for(i=0; i< 8; i++) // 下一个周期,发送数据取增量。
{
sdataB[i] = (sdataB[i]-1) & 0x00FF;
// 这里有2个sdataB[i],后一个sdataB[i]是从先前sdataB[]数组中取第i个元素,在减1并
/ / 屏蔽高8位后重新赋值给第i个元素。
// 假如先前一个数组的8个元素为: DC,DD,DE,DF,E0,E1,E2,E3
// 则后一个数组的8个元素为: DB,DC,DD,DE,DF,E0,E1,E2
}
ScibRegs.SCIFFTX.bit.TXINTCLR=1; // SCIFFTX[6]为TXINTCLR位,该位置
// 1清除SCI中断标志位TXFFIN
PieCtrlRegs.PIEACK.all|=0x100; // 发出PIE应答,以示响应INT9中断 }
//*******************************************************************************************
// 函数: scibRxFifoIsr()
// 标题: SCI_B 接收先进先出(FIFO)中断服务子程序(ISR)
//*******************************************************************************************
interrupt void scibRxFifoIsr(void)
{
Uint16 i;
for(i=0;i<8;i++) {rdataB[i]=ScibRegs.SCIRXBUF.all; }
// 读出接收缓冲器SCIRXBUF中的数据,放入接收数组第i位,读出8个数据
for(i=0;i<8;i++) // 检查接收的数据
{
if(rdataB[i] != ( (rdata_pointB-i) & 0x00FF) ) error();
// 检测rdataB[i]与(rdata_pointB-i)对应8个数据相等否,不等转出错处理,终止仿真调试;
// 相等顺执。
// 由于rdata_pointB 跟踪发送数组B sdataB[]中的第一个元素,因此 (rdata_pointB-i) 即为
// 发送数组的对应元素。
// 接收数组第i个元素rdataB[i]为发送数组B sdataB[]中的第i个元素,
// rdataB[i]与(rdata_pointB-i)两者相等,传送无误,否则出错。
// 这里用到DSP281x串行传送的内部回送功能。
}
//*******************************************************************************************
// 以下3行指令作用为:
// (1) 将McBSP回送值按顺序存入外存地址0x13f000开始的对应的44个单元。
// (2) Xaddr_track为地址跟踪指针,当Xaddr_track同步递增到44时复位地址指针及地址跟踪指针。 //*******************************************************************************************
for(i=0; i<8; i++)
{
if(Xaddr_track>43) {Xaddr=(Uint16 *)0x13f000;Xaddr_track=0;}
*Xaddr++ = rdataB[i];
Xaddr_track++;
}
rdata_pointB = (rdata_pointB-1) & 0x00FF; // 指向下一次发送数组第一个元素
ScibRegs.SCIFFRX.bit.RXFFOVRCLR=1; // 清除溢出标志位
ScibRegs.SCIFFRX.bit.RXFFINTCLR=1; // 清除中断标志位
PieCtrlRegs.PIEACK.all|=0x100; // 发出PIE应答,以示响应INT9中断
// PIEACK与0x100按位或后再对
// PIEACK赋值
}
//******************************************************************************************
// 函数: scib_fifo_init()
// 功能: SCI_B 先进先出(FIFO)初始化子程序
//******************************************************************************************
void scib_fifo_init()
{
ScibRegs.SCICCR.all =0x0007;
// 对SCI通信控制寄存器(SCICCR)进行配置。一个结束位,禁止回送,
// 禁止极性功能,8位字符,异步方式,选择空闲线协议。
ScibRegs.SCICTL1.all =0x0003;
// 使能TX, RX, 内部SCICLK,禁止接收错误中断,禁止睡眠,禁止TXWAKE
ScibRegs.SCICTL2.bit.TXINTENA =1;
// SCITXBUF中断使能,表示SCITXBUF寄存器准备接收下一个字符。
ScibRegs.SCICTL2.bit.RXBKINTENA =1;
// 启动接收缓冲器/中断。该位对SCI接收状态寄存器(SCIRXST)的RXRDY
// 和BRKDT标志(SCIRXST.6及.5位)位进行控制
//ScibRegs.SCIHBAUD =0x0000;
//ScibRegs.SCILBAUD =SCI_PRD;
ScibRegs.SCIHBAUD =0x0000;//=0x0001; // BOAT=9600,与串行调试助手9600
ScibRegs.SCILBAUD =0x00f5;//=0xE7; // 波特率匹配,通过
ScibRegs.SCICCR.bit.LOOPBKENA =1; // 启动回送测试功能
ScibRegs.SCIFFTX.all=0xC028; // SCI FIFO 发送寄存器(SCIFFTX)
// SCI FIFO重新开始和接收,使能
// SCI FIFO的增强型功能
// 使能匹配中断,FIFO级位为8
ScibRegs.SCIFFRX.all=0x0028; // 使能匹配中断,FIFO级位为8
//ScibRegs.SCIFFCT.all=0x00; // SCI FIFO 控制寄存器(SCIFFCT)
ScibRegs.SCICTL1.all =0x0023; // Relinquish SCI from Reset
ScibRegs.SCIFFTX.bit.TXFIFOXRESET=1;
ScibRegs.SCIFFRX.bit.RXFIFORESET=1; }
/*******************************************************************************************
函数名称: delay(Uint16 dly)
函数功能: 延时函数
输入参数: 形参dly,dly越大延时越久
输出参数: 无
*******************************************************************************************/
void delay(Uint16 dly)
{
Uint16 i;
for(;dly>0;dly--)
{
for(i=0;i<60000;i++);
}
}
//================================================================================
// No more.
//================================================================================
实验4 SPI实验
一、Spi数字回送实验
文件: Spi_FFDLB.c DSP281x 器件Spi数字回送程序
条件: 本程序需要DSP281x V1.00头文件支持,另外还需配置成"boot to H0"操作方式。除了boot方式
引脚配置外,不需要其他的硬件配置。
说明: 这个程序是一个采用外设内部回送的SPI示例。不使用中断。
送出数据流然后与接收到的数据流进行比较。
另外在以下2个方面对TI提供的驱动源码进行了硬件和软件的增强:
(1) 增加了LED数码管显示的硬件接口。以便将SPI通信的次数显示在LED数码管上。
(2) 增加了液晶屏显示硬件接口,用于刷新显示SPI回送的数据流。
送出数据如下所示: 0000 0001 0002 0003 0004 0005 0006 0007 .... FFFE FFFF周而复始重复这种
方式。
观察变量:
sdata - 送出数据
rdata - 接收数据
********************************************************************************************
#include "DSP281x_Device.h" // DSP281x头文件包含文件 #include "DSP281x_Examples.h" // DSP281x范例包含文件
// 由本文件建立的函数原型声明
void spi_xmit(Uint16 a); // SPI发送一个字符
void spi_fifo_init(void); // SPI FIFO 先进先出初始化 void spi_init(void); // SPI初始化
void error(void); // 出错处理函数,一旦数据传送有误终止仿真. void delay(Uint16 dly); // 延时函数
void LedD_Display(void);
// 将SPI发送次数以10进制形式,在Led第4,3,2,1位数码管上进行显示(右边起数1) void LedH_Display(void);
// 将SPI发送次数以16进制形式,在Led第8,7,6,5位数码管上进行显示 Uint16 count=0;
Uint16 *Xaddr=(Uint16 *)0x13f000;
// 指针变量定义。外存地址0x13f000为McBSP回送数据存入的首地址 Uint16 Xaddr_track=0;
// 外存地址跟踪指针
void main(void)
{
Uint16 sdata; // 送出数据
Uint16 rdata; // 接收数据
// 步骤1 系统控制初始化: 锁相环(PLL),看门狗(WatchDog)及外设时钟初始化。
// InitSysCtrl()函数由DSP281x_SysCtrl.c文件建立。
InitSysCtrl();
// 步骤2。初始化GPIO
// InitGpio()函数例举怎样将GPIO设置成其默认方式,该函数由DSP281x_Gpio.c文件建立。
//InitGpio(); // 本例跳过这个函数
lcd_init(); // Lcd 初始化。
clearscr1(); // 清除第一显示缓冲区:0x0000-0x29ff。
clearscr2(); // 清除第二显示缓冲区:0x2a00-0x53ff。
clearscr3(); // 清除第三显示缓冲区:0x5400-0x7FFF。
Disp_XramTab(); // 液晶屏界面显示。
// 只设置GP I/O端口的SPI功能
EALLOW; // 允许访问受保护的寄存器
GpioMuxRegs.GPFMUX.all=0x000F; // 选择GPIOs的SPI引脚: 多路器F端
// 口- 0000 0000 0000 1111 B
EDIS; // 禁止访问受保护的寄存器
// 步骤3 关所有中断并初始化PIE向量表:
DINT; // 关CPU中断
InitPieCtrl(); // 初始化PIE控制寄存器为默认状态,该状态关所有PIE中断并清所
// 有
// PIE中断标识符。这个函数由DSP281x_PieCtrl.c文件建立。
IER = 0x0000; // 关CPU中断并清所有CPU中断标识符。
IFR = 0x0000;
InitPieVectTable(); // 初始化PIE向量表,该向量表指明了中断服务程序(ISR)的一种构
// 架。
// 即使在这个示例中用不到中断,仍板上组装了整个PIE向量表。
// 作为调试目的这是很有用的。ISR程序架构由
// DSP281x_DefaultIsr.c文件建立。这个函数由
// DSP281x_PieVect.c文件建立。
// 步骤4 初始化器件外设: 这个函数由DSP281x_InitPeripherals.c文件建立。
//InitPeripherals(); // 本范例跳过这个函数
spi_fifo_init(); // 初始化 Spi FIFO
spi_init(); // 初始化 SPI
// 步骤5 用户绝对代码. 本例不用中断。
sdata = 0x0;
for(;;)
{
Uint16 i;
spi_xmit(sdata); // 传送数据
while(SpiaRegs.SPIFFRX.bit.RXFFST !=1) { } // 一直等到数据被接收。
// RXFFST 为SPIFFRX的接收状态位,表征FIFO接收到的字数。当RXFFST=0时,没有
// 接收到数据,等待; 当RXFFST=1时,接收到一个字,转下面程序。
rdata = SpiaRegs.SPIRXBUF; // 以下2条指令检查发送的数据与接收的数
// 据是否相等,
if(rdata != sdata) error(); // 若不等转出错处理,若相等跳转 "sdata++;"指令。
//while(SpiaRegs.SPISTS.bit.BUFFULL_FLAG ==1) { }
sdata++;
count=sdata;
//*******************************************************************************************
// 以下3行指令作用为:
// (1) 将SPI回送值按顺序存入外存地址0x13f000开始的对应的44个单元。
// (2) Xaddr_track为地址跟踪指针,当Xaddr_track同步递增到44时复位地址指针
// 及地址跟踪指针。
//*******************************************************************************************
if(Xaddr_track>43) {Xaddr=(Uint16 *)0x13f000;Xaddr_track=0;}
*Xaddr++ = rdata;
Xaddr_track++;
LedD_Display(); // 数码管显示发送的数字。
LedH_Display();
//DispXram_D((Uint16 *)0x13f000);
// 在液晶屏上以10进制显示存储区0x13f000-0x13f02b中的一块数据。
DispXram_H((Uint16 *)0x13f000);
// 在液晶屏上以16进制显示存储区0x13f000-0x13f02b中的一块数据。
delay(10);
}
}
// 步骤7. 在这里插入与本程序有关的函数
/*******************************************************************************************
函数: error(void)
功能: 出错处理函数,一旦数据传送有误终止仿真.
*******************************************************************************************/
void error(void)
{
asm(" ESTOP0"); // 检测到错误停止!
for (;;);
}
/*******************************************************************************************
函数: spi_init()
功能: SPI初始化
*******************************************************************************************/
void spi_init()
{
SpiaRegs.SPICCR.all =0x000F; // 复位,上升沿,16位字 (P517)
SpiaRegs.SPICTL.all =0x0006; // 使能主机模式, (P519)
// 普通时钟
,使能发送,关SPI中断。
SpiaRegs.SPIBRR =0x007F; // 波特率设置 (P521)
SpiaRegs.SPICCR.all =0x009F; // SPI准备发送或接收,
// 使能SPI回送模式,SIMO/SOMI线内部连接。
SpiaRegs.SPIPRI.bit.FREE = 1; // 空转。忽视中断挂起,SPI继续工作。 (P527)
}
/*******************************************************************************************
函数: spi_xmit(Uint16 a)
功能: SPI发送一个字符
*******************************************************************************************/
void spi_xmit(Uint16 a)
{
SpiaRegs.SPITXBUF=a; // 发送一个字符 (P523) }
/*******************************************************************************************
函数: spi_fifo_init()
功能: SPI FIFO 先进先出初始化
*******************************************************************************************/
void spi_fifo_init() // 初始化 SPI FIFO 寄存器。 {
SpiaRegs.SPIFFTX.all=0xE040;
// SPIFFTX.15=SPIRST=1, SPI FIFO 重新开始发送和接收。 (P524)
// SPIFFTX.14=SPIFFENA=1, 使能SPI FIFO 的增强型功能。
// SPIFFTX.13=TXFIFO=1, 重新使能接收FIFO 功能。
// SPIFFTX.12-8=TXFFST4-0=0, 发送 FIFO中空。
// SPIFFTX.7=TXFFINT=0, 不产生TXFIFO中断。
// SPIFFTX.6=TXFFINT CLR=1, 清除第7位TXFFINT的标志位。
// SPIFFTX.5=TXFFIIENA=0, 禁止基于TXFFIL匹配的TXFIFO中断
// SPIFFTX.4-0=TXFFIL4-0=0, 当FIFO状态位(TXFFST4-0)和FIFO级位
// (TXFFIL4-0)匹配时,发送FIFO产生中// 断。
// 由于发送状态位均比级位0大,故禁
// 止发送FIFO中断。
SpiaRegs.SPIFFRX.all=0x204f;
// SPIFFRX.15=RXFFOVF=0, 接收FIFO没有溢出。 (P525)
// SPIFFRX.14=RXFFOVF CLR=0, 清除第15位RXFFOVF标志位。
// SPIFFRX.13=RXFIFO=1, 重新使能接收FIFO的操作。
// SPIFFRX.12-8=RXFFST4-0=0, 接收FIFO中空。
// SPIFFRX.7=RXFFINT=0, 不产生RXFIFO中断。
// SPIFFRX.6=RXFFINT CLR=1, 清除第7位RXFFINT标志位。
// SPIFFRX.5=RXFFIENA=0, 禁止基于RXFFIL匹配的RXFIFO中断
// SPIFFRX.4-0=RXFFIL4-0=01111, 当FIFO状态位(RXFFST4-0)和FIFO级
// 位(RXFFIL4-0)匹配时,接收FIFO产
// 生中断。
// 由于接收状态位均比级位1111小,故
// 禁止接收FIFO中断。
SpiaRegs.SPIFFCT.all=0x0;
// FIFO发送延时为0。 (P526) }
/*******************************************************************************************
函数名称: delay(Uint16 dly)
函数功能: 延时函数
输入参数: 形参dly,dly越大延时越久
输出参数: 无
*******************************************************************************************/
void delay(Uint16 dly)
{
Uint16 i;
for(;dly>0;dly--)
{
for(i=0;i<60000;i++);
}
}
//================================================================================
// No more.
//================================================================================
二、Spi DAC实验
文件: DACtest.c
标题: DSP281x 器件数模(DAC)转换测试程序.
条件: 本程序需要DSP281x V1.00头文件支持,另外需配置成"boot to H0"操作方式。除了boot方式引
脚配置外,无需其他硬件配置方式。
说明: (1) 数模转换芯片TLV5614与DSP2812的通信采用SPI方式,通过中断进行;
(2) 数据的发送由中断服务程序spiTxFifoIsr()完成。数据发送指令:
"SpiaRegs.SPITXBUF=0x0000+temp; " 的赋值包含两个意思。 其中,0<=temp<0x1000,用于控制电
压值;而0x0000实际用到的只有最高4位,位功能定义参见后面的TLV5614简介。
(3) 由于最高2位为0,因此数模转换输出选择A通道。程序运行后,可用万用表检测A通道的
电压的周期性变化。
(4) SPI数据发送通过DSP2812的SPISIMOA(GPIOF0)引脚完成,SPI同步时钟及帧脉冲信号由
SPI通信内部机制完成,用户不必关注。
(5) DAC 输出数据更新受SCIRXDB(GPIOG5)引脚控制。
TLV5614简介:
友情提醒:请参照大板原理图看下面一段文字。
(1) 引脚功能
TLV5614与DSP2812通过4根线连接。其中3根用于SPI通信,对应连接为:
DIN <- SPISIMOA(GPIOF0),
SCLK <- SPICLKA(GPIOF2),
FS <- SPISTEA(GPIOF3).
TLV5614的DIN引脚接收来自DSP的串行数字输入,SCLK为串行时钟输入引脚,FS为帧同步
输入引脚。另一根线用于控制输出更新。其连接为:LDAC <- SCIRXDB(GPIOG5).当 LDAC 为高电
平时,DAC输出不进行更新;只有当LDAC 为低电平时,DAC输出才进行更新。
(2) 数据格式
TLV5614接收的16位数字输入包含两个部分:
第一部分:控制位(D15,D14,D13,D12)
第二部分:新DAC值(D12,D11,...,D1,D0)
_____________________________________________________________
| D15| D14| D13| D12| D11| D10| D9| D8| D7| D6| D5| D4| D3| D2| D1| D0|
|____|____|____|____|____|____|___|___|___|___|___|___|___|___|___|___|
| A1 | A0| PWR| SPD| 新DAC值(12位) |
|____|____|____|____|__________________________________________|
SPD: 速度控制位 SPD=1,快模式;SPD=0,慢模式。
PWR: 电源控制位 PWR=1,掉电;PWR=0,正常操作。
在掉电状态下,关闭TLV5614内部所有放大器。通过输入字的A1,A0位可对DAC的A,B,
C,D
4个输出通道进行选择。
A1 A0 DAC输出
0 0 OUTA
0 1 OUTB
1 0 OUTC
1 1 OUTD
*******************************************************************************************/
#include "DSP281x_Device.h" // DSP281x 头文件包含文件 #include "DSP281x_Examples.h" // DSP281x 示例件包含文件
// 由本文件建立的函数原型声明。
interrupt void spiTxFifoIsr(void); //interrupt void spiRxFifoIsr(void); void spi_fifo_init(void);
void error();
void delay();
Uint16 sdata[8]; // 发送数据缓冲器
Uint16 rdata[8]; // 接收数据缓冲器
Uint16 rdata_point; // 跟踪数据流用以检查接收数据 Uint16 temp=0;
void main(void)
{
Uint16 i;
// 步骤1 系统控制初始化:
// 锁相环(PLL),看门狗(WatchDog)及外设时钟(PeripheralClocks)初始化。
// 这个函数由DSP281x_SysCtrl.c文件建立。
InitSysCtrl();
// 步骤2。初始化GPIO
// InitGpio()函数例举怎样将GPIO设置成其默认状态,该函数由DSP281x_Gpio.c
// 文件建立。
//InitGpio(); // 本例跳过这个函数。
// 仅设置GP I/O的SPI功能
EALLOW;
GpioMuxRegs.GPFMUX.all=0x000F; // 选择GPIOs 的SPI引脚
// Port F MUX - x000 0000 0000 1111
EDIS;
EALLOW;
GpioMuxRegs.GPGDIR.bit.GPIOG5=1; // GPIOG5引脚用于控制DAC输出数据更新。
EDIS;
// 步骤3 关所有中断并初始化PIE向量表:
DINT;
IER = 0x0000;
IFR = 0x0000;
// 初始化PIE控制寄存器为默认状态.
// InitPieCtrl()函数由DSP281x_PieCtrl.c文件建立。
InitPieCtrl();
// 初始化PIE向量表,该向量表指明了中断服务程序(ISR)的一种构架。
// 即使在这个示例中用不到中断,仍板上组装了整个PIE向量表。作为调试
// 目的这是很有用的。ISR程序架构由DSP281x_DefaultIsr.c文件建立。
// InitPieVectTable()函数由DSP281x_PieVect.c文件建立。
InitPieVectTable();
// 本例所用的中断从新映射到由本文件建立的ISR函数中。 //*******************************************************************************************
// 关于 "PieVectTable.SPITXINTA = &spiTxFifoIsr;" 指令的说明 // 1. spiTxFifoIsr 是一个SPI发送先进先出中断服务程序(ISR)。
// 2. 这个中断程序与中断扩展(PIE)向量表第6组INT6第2个中断向量SPITXINTA(SPI)对应。 // 3. 为了使这个程序响应对应的中断,还需作如下配置:
// PieCtrlRegs.PIECRTL.bit.ENPIE = 1; // 使能PIE向量表。这条指令包含在上面调用的InitPieVectTable()函数中。后续指令又重复了这条指令。 // IER=0x20; // 使能PIE向量表第6组(CPU INT6)中断 // PieCtrlRegs.PIEIER6.bit.INTx2=1; // 使能PIE向量表第6组第2个 // SPITXINTA中断
// EINT; // 使能全局中断(清INTM位) // 这几条指令在本程序的后续指令中可以找到。这样,在发生SPI中断的情况下,将执行spiTxFifoIsr()
// 中断服务程序。"PieVectTable.SPITXINTA = &spiTxFifoIsr;" 指令实际上就是通知编译器,在发生SPI // 中断的情况下,将执行spiTxFifoIsr()中断服务程序。spiTxFifoIsr头上的"&"为取地址运算符。 //*******************************************************************************************
EALLOW; // 允许访问受保护的寄存器。
PieVectTable.SPITXINTA = &spiTxFifoIsr;
//PieVectTable.SPIRXINTA = &spiRxFifoIsr;
EDIS; // 禁止访问受保护的寄存器。
// 步骤4 初始化器件所有外设: InitPeripherals()函数由DSP281x_InitPeripherals.c文
// 件建立。
//InitPeripherals(); // 本例跳过这个函数。
spi_fifo_init(); // 仅对SPI进行初始化
// 步骤5 用户代码,中断使能:
for(i=0; i<8; i++) // 初始化发送数据缓冲区
{
sdata[i] = i;
}
rdata_point = 0;
GpioDataRegs.GPFDAT.bit.GPIOF4=1;
GpioDataRegs.GPFDAT.bit.GPIOF5 =0;
// 使能本例所需的中断
PieCtrlRegs.PIECRTL.bit.ENPIE = 1; // 使能PIE 模块
PieCtrlRegs.PIEIER6.bit.INTx2=1; // 使能PIE向量表第6组第2个
// SPITXINTA中断
//PieCtrlRegs.PIEIER6.bit.INTx1=1; // 使能PIE向量表第6组第1个
// SPIRXINTA中断
IER=0x20; // 使能CPU INT6 第6组中断
EINT; // 使能全局中断
// 步骤6 空循环
for(;;);
}
// 一些有用的局部函数
/*******************************************************************************************
函数名称: error(void)
函数功能: 错误处理函数
输入参数: 无
输出参数: 无
*******************************************************************************************/
void error(void)
{
asm(" ESTOP0"); // 检测到错误,停止。
for (;;);
}
/*******************************************************************************************
函数名称: spi_fifo_init()
函数功能: 初始化SPI先进先出寄存器用于数模转换
输入参数: 无
输出参数: 无
*******************************************************************************************/
void spi_fifo_init() {
SpiaRegs.SPICCR.bit.SPISWRESET=0; // 复位 SPI
SpiaRegs.SPICCR.all=0x000F; // 16位字,禁止回送模式
SpiaRegs.SPICTL.all=0x0017; // 中断使能,主/从 XMIT 使能
SpiaRegs.SPISTS.all=0x0000;
SpiaRegs.SPIBRR=0x0063; // 波特率设置
SpiaRegs.SPIFFTX.all=0xC028; // 使能FIFO, 设置TX FIFO 级别为8
SpiaRegs.SPIFFRX.all=0x0028; // 设置RX FIFO 级别为31
SpiaRegs.SPIFFCT.all=0x00;
SpiaRegs.SPIPRI.all=0x0010;
SpiaRegs.SPICCR.bit.SPISWRESET=1; // 使能 SPI
SpiaRegs.SPIFFTX.bit.TXFIFO=1;
SpiaRegs.SPIFFRX.bit.RXFIFORESET=1; }
/*******************************************************************************************
函数名称: spiTxFifoIsr()
函数功能: SPI发送先进先出中断服务程序(ISR)
输入参数: 无
输出参数: 无
*******************************************************************************************/
interrupt void spiTxFifoIsr(void) {
SpiaRegs.SPITXBUF=0x0000+temp; // 通过SPISIMOA引脚发送数据。
// 0x0000用意为选择OUTA输出通道,慢
// 模式。
temp+=0x1;
if(temp==0x1000) {temp=0;}
GpioDataRegs.GPGCLEAR.bit.GPIOG5=1; // 更新数模转换输出数据
GpioDataRegs.GPGSET.bit.GPIOG5=1; // 保持数模转换输出数据
SpiaRegs.SPIFFTX.bit.TXFFINTCLR=1; // 清中断标志位
PieCtrlRegs.PIEACK.all|=0x20; // 发布PIE应答
delay(1);
}
/*******************************************************************************************
函数名称: spiRxFifoIsr()
函数功能: SPI接收先进先出中断服务程序(ISR)
输入参数: 无
输出参数: 无
*******************************************************************************************/
interrupt void spiRxFifoIsr(void) {
Uint16 i;
for(i=0;i<8;i++)
{
rdata[i]=SpiaRegs.SPIRXBUF; // 读数据
}
for(i=0;i<8;i++) // 检查接收数据检查接收数据
{
if(rdata[i] != rdata_point+i) error();
}
rdata_point++;
SpiaRegs.SPIFFRX.bit.RXFFOVFCLR=1; // 清溢出标志位
SpiaRegs.SPIFFRX.bit.RXFFINTCLR=1; // 清中断标志位
PieCtrlRegs.PIEACK.all|=0x20; // 发布PIE应答
}
/*******************************************************************************************
函数名称: delay(Uint16 dly)
函数功能: 延时函数
输入参数: 形参dly,dly越大延时越久
输出参数: 无
*******************************************************************************************/ void delay(Uint16 dly)
{
Uint16 i;
for(;dly>0;dly--)
{
for(i=0;i<60000;i++);
}
}
//================================================================================ // No more.
//================================================================================
实验5 看门狗实验
文件: Watchdog.c DSP281x看门狗中断测试程序
条件: 本程序需DSP281x V1.00头文件支持,另外还需配置成"boot to H0"操作方式。
除了boot方式引脚配置外,不需其他的硬件配置。
说明: 本例是针对F2812/F2810系列的一个看门狗演练程序。
首先将看门狗连接到PIE模块的WAKEINT中断。然后程序代码进入无限循环。用户可通过选
择在无限循环中有注释的一行代码决定是否喂狗。若通过KickDog函数喂狗,那么WAKEINT中断就
不会产生。否则将产生中断。
观察变量:LoopCount 无限循环次数
WakeCount WAKEINT中断次数
*******************************************************************************************/
#include "DSP281x_Device.h" // DSP281x 头文件包含文件 #include "DSP281x_Examples.h" // DSP281x Examples Include File
// 本文件建立的函数原型声明
interrupt void wakeint_isr(void);
// 由Bc7281.c文件建立的函数原型声明
void LedD_Display(void); // 在右边4个数码管上以10进制显示看门狗中断中断的次数。 void LedH_Display(void); // 在左边4个数码管上以16进制显示看门狗中断中断的次数。
// 全局变量
Uint16 count;
Uint32 WakeCount;
// 中断计数器,全局变量声明,以便外部函数display引用
Uint32 LoopCount;
void main(void)
{
// 步骤1. 初始化系统控制:PLL, WatchDog,使能外设时钟
// InitSysCtrl()函数由DSP281x_SysCtrl文件建立
InitSysCtrl();
// 步骤2. 初始化GPIO。
// InitGpio()函数由DSP281x_Gpio.c文件建立,该文件阐明如何将GPIO
// 设置为默认状态。
// InitGpio(); // 本范例跳过该函数
// 步骤3. 关闭所有中断并初始化PIE向量表:
// 关CPU中断
DINT; // 禁止可屏蔽中断。
// 将PIE控制寄存器初始化为默认状态,该状态关所有PIE中断并清除所有
// 标志。InitPieCtrl()函数由DSP281x_PieCtrl.c文件建立。
InitPieCtrl();
// 关CPU中断并清除所有CPU中断标志
IER = 0x0000;
IFR = 0x0000;
// 初始化PIE向量表,该向量表指明了中断服务程序(ISR)的一种构架。
// 即使在这个示例中用不到中断,仍板上组装了整个PIE向量表。作为调试目的这是很有用的。
// ISR程序架构由DSP281x_DefaultIsr.c文件建立。
// InitPieVectTable()函数由DSP281x_PieVect.c文件建立。
InitPieVectTable();
// 本示例使用的中断重新映射到由本文件建立的ISR函数中。
EALLOW; // 允许访问受保护的寄存器
PieVectTable.WAKEINT = &wakeint_isr;
EDIS; // 禁止访问受保护的寄存器
// 步骤4. 初始化器件所有外设。
// InitPeripherals()函数由DSP281x_InitPeripherals.c文件建立。
// InitPeripherals(); // 本程序不需要对外围器件初始化
// 步骤5. 应用代码,中断使能
WakeCount = 0; // 中断计数器清0。
LoopCount = 0; // (空循环)计数器清0。
// 将看门狗连接到PIE的WAKEINT中断
// 写整个SCSR寄存器以免清WDOVERRIDE位。
EALLOW; // 允许访问受保护的寄存器
SysCtrlRegs.SCSR = BIT1; // SCSR=BIT1=0x0002,看门狗中断有效 (P161)
// SCSR[15:3]=Reserved\ 保留
// SCSR[2]=WDINTS 看门狗中断状态位,该位反映了来自看门狗模块的WDINT信
// 号的当前状态
// SCSR[1]=WDENINT 如果该位置1,看门狗复位(WDRST)输出信号无效并且看门狗
// 中断(WDINT)输出信号有效。如果该位清0,看门狗复位
// (WDRST)输出信号有效并且看门狗中断(WDINT)输出信号无效,
// 这是复位后的默认状态(XRS)
// SCSR[0]=WDOVERRIDE 如果该位置1,允许用户改变看门狗控制(SDCR)寄存器中
// 的看门狗无效(WDDIS)位的状态。如果该位清0,用户不
// 能通过向该位写1来修改它。写0无效。如该位清0,那麽
// 它将保持本状态直到复位发生。该位的当前状态用户可读。
// 注意: 这里的BIT1是一个位掩码。通过DSP281x_Device.h文件中的宏定义指令:
// "#define BIT1 0x0002" 定义。这里不用位域方式而是采用位掩码的形
// 式写整个SCSR寄存器,是为了避免位域方式可能会清WDOVERRIDE位。这
// 条指令实际是置WDENINT=1,即看门狗复位(WDRST)输出信号无效且看门
// 狗中断(WDINT)输出信号有效。
EDIS; // 禁止访问受保护的寄存器
PieCtrlRegs.PIECRTL.bit.ENPIE = 1; // PIECRTL:PIE中断控制寄存器。 (P185)
// PIECRTL[0]=ENPIE=1,当ENPIE=1,所有向量取自PIE向量表,PIE模块使能;
// 当ENPIE=0,PIE模块无效。
PieCtrlRegs.PIEIER1.bit.INTx8 = 1; // PIEIER1:PIE中断使能寄存器。 (P186)
// PIEIER1[7]= INTx8=1,使能PIE 第1组第8个中断(即WAKEINT中断);
// 否则,使该位中断服务无效
IER |= M_INT1; // IER:CPU中断使能寄存器。 \ (P57,P181)
// IER[0]=INT1=1,CPU INT1中断使能(M_INT1=0x0001)。
// 即使能WAKEINT中断并使能连接WAKEINT的INT1以上中断设置:
EINT; // 全局中断使能
KickDog(); // 复位看门狗计数器
EALLOW; // 允许访问受保护的寄存器
SysCtrlRegs.WDCR = 0x0028; // WDCR: 看门狗控制寄存器: (P169)
// WDCR[15:8]=Reserved,高8位保留
// WDCR[7]=WDFLAG=0,看门狗复位状态标志位。如果该位置位,表示一个看门狗
// 复位(WDRST)产生了复位条件。如果为0,则是一个外部器
// 件或加电复位条件。 该位保存锁存状态直到写一个1清除
// 此条件,写0无效。
// WDCR[6]=WDDIS=0, 看门狗使能; 若写1则关看门狗。
// WDCR[5:3]=WDCHK(2-0)=101b,无论何时执行写此寄存器的操作,必须将这些位写成101b,
// 写其他值将使核立即复位。
// WDCR[2:0]=WDPS(2-0)=000b,这些位以OSCCLK/512为时基来配置看门狗的时钟(WDCLK)
// 速率,000b WDCLK=(OSCCLK/512)/1
EDIS; // 禁止访问受保护的寄存器
// 步骤6.空循环. IDLE loop. Just sit and loop forever (optional):
for(;;)
{
if (LoopCount>9999) LoopCount=0;
LoopCount++;
//KickDog(); // KickDog()函数前不加 "//" 注释符,即喂狗,程序在此循环;
// 加上 "//" 注释符,即不喂狗,将会产生看门狗中断。
// KickDog()函数在DSP281x_SysCtrl.c文件中建立。
}
}
// 步骤7.
// 此处可嵌入所有局部中断服务程序及函数,若用到局部中断服务程序(ISRs),要如步骤5所示再分配向 // 量表中向量的地址
/*******************************************************************************************
函数名称: interrupt void wakeint_isr(void) 看门狗中断程序
说 明: 一旦看门狗引起中断,即运行该程序。这里调用了LED显示函数。若在上面空循环模块中,屏
蔽喂狗函数KickDog(),则可通过LED显示,观察发生中断的次数; 若激活KickDog()函数,即喂狗,
则LED无动态数字显示。
*******************************************************************************************/
interrupt void wakeint_isr(void)
{
if (WakeCount>9999) WakeCount=0;
WakeCount++;
count=WakeCount;
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; // PIEACK: PIE中断应答寄存器 (见P185)
// PIEACK=[15:12]=Reserved,保留
// PIEACK[11:0]=PIEACK=0x0001,PIE第一组CPU通道INT1看门狗中断(WAKEINT)应答
// 注意: 这里的PIEACK_GROUP1是一个位掩码。通过DSP281x_PieCtrl.h文件中的
// 宏定义指令:"#define PIEACK_GROUP1 0x0001;" 定义。这里不用位域方
// 式而是采用位掩码的形式写整个PIEACK寄存器,是为了避免位域方式可
// 能会清PIEACK位。
LedH_Display(); // 在左边4个数码管上以16进制显示看门狗中断中断的次数。
LedD_Display(); // 在右边4个数码管上以10进制显示看门狗中断中断的次数。
}
//================================================================================ // No more.
//================================================================================
实验6 事件管理器实验
一、EvPwm实验
文件: EvPwm.c
标题: 通过事件管理产生PWM
条件: 本程序需要DSP281x V1.00头文件支持,另外需配置成"boot to H0"操作方式。
除了boot方式引脚配置外,无需其他硬件配置方式。
说明: 该程序设置EV定时器(TIMER1, TIMER2, TIMER3 and TIMER4),用于产生T1PWM, T2PWM,
T3PWM, T4PWM and PWM1-PWM12波形。可通过示波器观察这些波形。
在以下几个方面对TI提供的驱动源码进行了硬件和软件的增强:
(1) 增加了LED数码管显示的硬件接口。以便将EvPwm发生的次数反映在LED数码管上。
(2) 在更新EvPwm时,增加了受GPIO A控制的16个Led发光二极管的闪烁显示。
(3) 增加了320*240液晶屏及与之配套的软件。
*******************************************************************************************/
#include "DSP281x_Device.h" // DSP281x 头文件包含文件 #include "DSP281x_Examples.h" // DSP281x 示例包含文件
// 本文件建立的函数原型声明。
void init_eva(void); // EVA配置T1PWM, T2PWM, PWM1-PWM6 ,初始化定时器 void init_evb(void); // EVB配置T1PWM, T2PWM, PWM1-PWM6 ,初始化定时器 void delay(); // 延时函数
interrupt void adc_isr(void);
//Uint16 SampleTable[BUF_SIZE];
void OscillographTable(); // 制作示波器
//void AdcAverage();
void VoltageCurve();
void AdcResultCopy();
//void delay(Uint16 dly);
Uint16 *Xaddr=(Uint16 *)0x13f000; Uint16 Xram_pointer=0;
//#define BUF_SIZE 256 // 采样缓冲器大小
// 本例的全局变量
//Uint16 SampleTable[BUF_SIZE];
// 外部函数声明。由Bc7281.c 文件建立
void LedD_Display(void);
// 将模数转换值以10进制形式,在Led第4,3,2,1位数码管上进行显示 void LedH_Display(void);
// 将模数转换值以16进制两个字节形式,在Led第8,7,6,5位数码管上进行显示
// 本例中的全局计数器
int count=0,i;
void main(void)
{
// 步骤1 系统控制初始化: 锁相环(PLL),看门狗(WatchDog)及外设时钟
// (PeripheralClocks)初始化。该函数在DSP281x_SysCtrl.c文件中建立。
InitSysCtrl();
// 步骤2.初始化GPIO:
// 这个函数例举怎样将GPIO设置成其默认状态,该函数由DSP281x_Gpio.c文件建立。
//InitGpio(); // 本例跳过这个函数
lcd_init();
clearscr1(); // 第一显示缓冲区(0x0000-0x29ff)清零
clearscr2(); // 第二显示缓冲区(0x2a00-0x53ff)清零
clearscr3(); // 第三显示缓冲区(0x5400-0x7dff)清零
OscillographTable();
// 对于这个检测仅初始化GPAMUX和GPBMUX
EALLOW; // 允许访问受保护的空间
GpioMuxRegs.GPAMUX.all = 0x00FF; // 使能EVA PWM 1-6 脚
GpioMuxRegs.GPBMUX.all = 0x00FF; // 使能EVB PWM 7-12 脚
EDIS; //禁止访问受保护的空间
EALLOW; // 允许访问受保护的寄存器
GpioMuxRegs.GPAMUX.all=0x0000; // 将A端口设置成IO方式
GpioMuxRegs.GPADIR.all=0xffff; // 将GPIO A所有15个端口配置成数字量输出
EDIS; // 禁止访问受保护的寄存器
GpioDataRegs.GPADAT.all=0xAAAA; // 间隔一个点亮LED发光二极管。
// 步骤3 关所有中断并初始化PWM矢量表
DINT; // 关CPU中断
InitPieCtrl(); // 初始化PIE控制寄存器为默认状态。该状态关所有PIE中断并清除所
// 有标识。该函数在DSP281x_PieCtrl.c文件中建立。
IER = 0x0000; // 关CPU中断并清CPU中断标识。
IFR = 0x0000;
InitPieVectTable();
// 初始化PIE向量表,该向量表指出中断服务程序(ISR)的构架。即使在本范例中
// 没有用到中断,仍旧组装整张表。它在程序调试时是很有用的。ISR程序构架由
// DSP281x_DefaultIsr.c文件建立
// InitPieVectTable()函数由DSP281x_PieVect.c文件建立
// 本例用到的中断重新映射到由本文件建立的ISR函数中。
//******************************************************************************************
// 关于 "PieVectTable.ADCINT = &adc_isr;" 指令的说明
// 1. adc_isr 是一个ADC模块中断服务程序(ISR)。
// 2. 这个中断程序与中断扩展(PIE)向量表第1组INT1第6个中断向量ADCINT(ADC)对应。 // 3. 为了使这个程序响应对应的中断,还需作如下配置:
// PieCtrlRegs.PIECRTL.bit.ENPIE = 1; // 使能PIE向量表。这条指令包含在上面调用的InitPieVectTable()函数中。 // IER |= M_INT1; // 使能PIE向量表第1组CPU INT1中断 // PieCtrlRegs.PIEIER1.bit.INTx6 = 1; // 使能PIE向量表第一组第6个ADCINT中断 // EINT; // 允许可屏蔽中断(清INTM位) // 这几条指令在本程序的后续指令中可以找到。这样,在发生ADCINT中断的情况下,将执行
// adc_isr()中断服务程序。
// "PieVectTable.ADCINT = &adc_isr;" 指令实际上就是通知编译器,在发生ADCINT中断的情况 // 下,将执行adc_isr()中断服务程序。adc_isr头上的"&"为取地址运算符。
//******************************************************************************************
EALLOW; // 允许访问受保护的寄存器
PieVectTable.ADCINT = &adc_isr;
EDIS; // 禁止访问受保护的寄存器
// 步骤4. 初始化器件所有外围设备:
//这个函数由DSP281x_InitPeripherals.c文件建立。
// InitPeripherals(); // 本例不需要
InitAdc(); // 初始化ADC模块
// Step 5. User specific code, enable interrupts:
// 步骤5. 用户代码,中断使能:
// Enable ADCINT in PIE
PieCtrlRegs.PIEIER1.bit.INTx6 = 1; // 使能PIE向量表第一组第6个ADCINT中断
IER |= M_INT1; // 使能CPU 第一组中断
EINT; // 允许可屏蔽中断(清INTM位)
ERTM; // ERTM指令在外围设备头文件(DSP281x_Device.h)中有定义:
// #define ERTM asm(" clrc DBGM")。即清除DBGM位,作用为使能全局实时中断 //******************************************************************************************
//关于输入通道选择序列控制寄存器注解:
// ADCCHSELSEQ1-ADCCHSELSEQ4 为4个16位ADC输入通道选择序列控制寄存器,从 // ADCCHSELSEQ1最低位开始,每一个4位值CONVnn(0<=nn<15)可以选择16个模拟输入通道(A通道或 // 是B通道)中的任何一路。每一个ADCCHSELSEQn(1<=n<=4)管理4个固定的CONVnn,其对应关系见下 // 面注释.输入通道选择个数必须与ADC最大转换通道(数)寄存器(ADCMAXCONV)的配置相匹配. // ADCCHSELSEQ1[3:0] =CONV00, ADCCHSELSEQ3[3:0] =CONV08, // ADCCHSELSEQ1[7:4] =CONV01, ADCCHSELSEQ3[7:4] =CONV09, // ADCCHSELSEQ1[11:8] =CONV02, ADCCHSELSEQ3[11:8] =CONV10, // ADCCHSELSEQ1[15:12]=CONV03, ADCCHSELSEQ3[15:12]=CONV11, // ADCCHSELSEQ2[3:0] =CONV04, ADCCHSELSEQ4[3:0] =CONV12, // ADCCHSELSEQ2[7:4] =CONV05, ADCCHSELSEQ4[7:4] =CONV13, // ADCCHSELSEQ2[11:8] =CONV06, ADCCHSELSEQ4[11:8] =CONV14, // ADCCHSELSEQ2[15:12]=CONV07, ADCCHSELSEQ4[15:12]=CONV15, //******************************************************************************************
AdcRegs.ADCMAXCONV.all = 0x000f; // 配置SEQ1模式16通道
AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x7; // 选择ADCINA0为SEQ模式第3通道
AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 0x7; // 选择ADCINA1为SEQ模式第3通道
AdcRegs.ADCCHSELSEQ1.bit.CONV02 = 0x7; // 选择ADCINA2为SEQ模式第3通道
AdcRegs.ADCCHSELSEQ1.bit.CONV03 = 0x7; // 选择ADCINA3为SEQ模式第3通道
AdcRegs.ADCCHSELSEQ2.bit.CONV04 = 0x7; // 选择ADCINA4为SEQ模式第3通道
AdcRegs.ADCCHSELSEQ2.bit.CONV05 = 0x7; // 选择ADCINA5为SEQ模式第3通道
AdcRegs.ADCCHSELSEQ2.bit.CONV06 = 0x7; // 选择ADCINA6为SEQ模式第3通道
AdcRegs.ADCCHSELSEQ2.bit.CONV07 = 0x7; // 选择ADCINA7为SEQ模式第3通道
AdcRegs.ADCCHSELSEQ3.bit.CONV08 = 0x7; // 选择ADCINB0为SEQ模式第3通道
AdcRegs.ADCCHSELSEQ3.bit.CONV09 = 0x7; // 选择ADCINB1为SEQ模式第3通道
AdcRegs.ADCCHSELSEQ3.bit.CONV10 = 0x7; // 选择ADCINB2为SEQ模式第3通道
AdcRegs.ADCCHSELSEQ3.bit.CONV11 = 0x7; // 选择ADCINB3为SEQ模式第3通道
AdcRegs.ADCCHSELSEQ4.bit.CONV12 = 0x7; // 选择ADCINB4为SEQ模式第3通道
AdcRegs.ADCCHSELSEQ4.bit.CONV13 = 0x7; // 选择ADCINB5为SEQ模式第3通道
AdcRegs.ADCCHSELSEQ4.bit.CONV14 = 0x7; // 选择ADCINB6为SEQ模式第3通道
AdcRegs.ADCCHSELSEQ4.bit.CONV15 = 0x7; // 选择ADCINB7为SEQ模式第3通道
AdcRegs.ADCTRL2.bit.EVA_SOC_SEQ1 = 1; // 使能EVASOC 启动SEQ1
AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 1; // 使能SEQ1 中断 (在每一个EOS时)
AdcRegs.ADCTRL3.bit.SMODE_SEL = 0; // 连续采样方式配置
// SMODE_SEL: 采样方式选择位。
// 当SMODE_SEL=0, 连续采样方式; 当SMODE_SEL=1, 并发采样方式。
// 所谓连续采样方式是指:一旦启动转换,则转换按照当前CONVxx决定的顺序
// 进行,xx 4位值的最高位确定是A引脚还是B引脚,低3位确定A引脚或B引脚
// 的偏移量,采样结果依次存入结果寄存器。在并发采样方式下,xx 最高位
// 被舍弃,系统根据低3位的偏移量先进行对应A引脚的采样再进行对应B引脚?
// 采样,采样结果也按照这一顺序存入结果寄存器。 (P352,P371)
AdcRegs.ADCTRL1.bit.SEQ_CASC = 1; // 级联方式配置
AdcRegs.ADCTRL2.bit.SOC_SEQ1 = 1;
// 启动SEQ1,触发模数转换。在级联方式下,SEQ1管理16个通道?
// SEQ2被忽略
// 配置 EVA。假定EVA时钟已经在InitSysCtrl()函数中被使能。
EvaRegs.T1CMPR = 0x0080; // 设置 T1 比较值
EvaRegs.T1PR = 0xFFFF; // 设置周期寄存器 如何确定中断周期。
EvaRegs.GPTCONA.bit.T1TOADC = 1; // 使能EVA 的EVASOC
EvaRegs.T1CON.all = 0x1042; // 使能定时器1比较
// 步骤4 初始化器件外设: 这个函数由DSP281x_InitPeripherals.c文件建立。
//InitPeripherals(); // 本例不需要这个函数
init_eva();
init_evb();
// 步骤5. 用户代码,中断使能:
// 无限循环. 可用示波器观察PWM引脚的波形。
for(;;)
{
if(count>9999) count=0;
count++;
clearscr1(); // 第一显示缓冲区(0x0000-0x29ff)清零
VoltageCurve(); // 在液晶屏上制作电压曲线
LedD_Display(); // 以十进制形式在数码管上显示count
LedH_Display(); // 以十六进制形式在数码管上显示count
GpioDataRegs.GPATOGGLE.all = 0xffff; // A端口取反,16个Led闪烁显示。
delay(1);
}
}
/*******************************************************************************************
函数名称: init_eva()
函数功能: EVA配置T1PWM, T2PWM, PWM1-PWM6 ,初始化定时器
*******************************************************************************************/
void init_eva()
{
//##################################################################
// EvbRegs.T3PR = 0xFFFF; // 定时器3周期设置 (P313) // EvbRegs.T3CMPR = 0x3C00; // 定时器3比较器设置
// EvbRegs.T3CNT = 0x0000; // 定时器3计数器设置
// EvbRegs.T3CON.all = 0x1042;
//##################################################################
// 初始化EVA定时器1
EvaRegs.T1PR = 0xFFFF; // 定时器1周期设置 (P313)
EvaRegs.T1CMPR = 0x3C00; // 定时器1比较器设置 (P313)
EvaRegs.T1CNT = 0x0000; // T定时器1计数器设置 (P313)
EvaRegs.T1CON.all =0x1042;
// T1CON[15]=Free=0, 与Soft合用。一旦仿真挂起,立即停止。 (P314)
// T1CON[14]=Soft=0,
// T1CON[13]=Reserved, 保留
// T1CON[12:11]=TMODE1=10 B, 连续递增模式。,
// T1CON[10:8]=TPS2-0=000 B, 不分频,输入时钟频率同CPU时钟频率。
// T1CON[7]=T2SWT1/T4SWT3=0, T2SWT1对应EVA,使用定时器2的使能位启动定时器1,
// T4SWT1对应EVB,使用定时器4的使能位启动定时器3。
// 使用自身的使能位。
// T1CON[6]=TENABLE=1, 定时器使能。
// T1CON[5:4]=TCLK1-0=00 B, 采用内部高速外设时钟(HSPCLK)
// T1CON[3:2]=TCLD1-0=00 B, 当计数器为0时,定时器比较寄存器重载。
// T1CON[1]=TECMPR=1, 定时器比较使能
// T1CON[0]=SELT1PR/SELT3PR=0,选用自身周期寄存器。
//######################################################################
// EvbRegs.T4PR = 0x00FF; // 定时器4周期设置 (P313) // EvbRegs.T4CMPR = 0x0030; // 定时器4比较器设置 (P313) // EvbRegs.T4CNT = 0x0000; // 定时器4计数器设置 (P313) // EvbRegs.T4CON.all = 0x1042;
//######################################################################
// 初始化EVA定时器2
EvaRegs.T2PR = 0x0FFF; // 定时器2周期设置 (P313)
EvaRegs.T2CMPR = 0x03C0; // 定时器2比较器设置 (P313)
EvaRegs.T2CNT = 0x0000; // 定时器2计数器设置 (P313)
EvaRegs.T2CON.all = 0x1042;
// T2CON[15]=Free=0, 与Soft合用。一旦仿真挂起,立即停止。 (P314)
// T2CON[14]=Soft=0,
// T2CON[13]=Reserved, 保留
// T2CON[12:11]=TMODE1=10 B, 连续递增模式。,
// T2CON[10:8]=TPS2-0=000 B, 不分频,输入时钟频率同CPU时钟频率。
// T2CON[7]=T2SWT1/T2SWT3=0, T2SWT1对应EVA,使用定时器2的使能位启动定时器1,
// T3SWT1对应EVB,使用定时器4的使能位启动定时器3。
// 使用自身的使能位。
// T2CON[6]=TENABLE=1, 定时器使能。
// T2CON[5:4]=TCLK1-0=00 B, 采用内部高速外设时钟(HSPCLK)
// T2CON[3:2]=TCLD1-0=00 B, 当计数器为0时,定时器比较寄存器重载。
// T2CON[1]=TECMPR=1, 定时器比较使能
// T2CON[0]=SELT1PR/SELT3PR=0,选用自身周期寄存器。
//############################################################################
// EvbRegs.GPTCONB.bit.TCMPOE = 1; // // GTPCONB[6]=TCMPOE=1,通过比较逻辑驱动T3/T4 PWM (P318) // EvbRegs.GPTCONB.bit.T3PIN = 1; // // GPTCONB[1:0]=T3PIN = 01,GP定时器3比较器输出极性低电平有效。 // EvbRegs.GPTCONB.bit.T4PIN = 2; // // GPTCONB[3:2]=T4PIN = 10,GP定时器4比较器输出极性高电平有效。 // // 使能PWM7-PWM12的比较功能
// EvbRegs.CMPR4 = 0x0C00;
// EvbRegs.CMPR5 = 0x3C00;
// EvbRegs.CMPR6 = 0xFC00;
//############################################################################
// 设置T1PWM及T2PWM
EvaRegs.GPTCONA.bit.TCMPOE = 1;
// GTPCONA[6]=TCMPOE=1,通过比较逻辑驱动T1/T2 PWM (P315)
EvaRegs.GPTCONA.bit.T1PIN = 1;
// GPTCONA[1:0]=T1PIN = 01 B,GP定时器1比较器输出极性低电平有效。
EvaRegs.GPTCONA.bit.T2PIN = 2;
// GPTCONA[3:2]=T2PIN = 10 B,GP定时器2比较器输出极性高电平有效。
// 使能PWM1-PWM6的比较功能
// 原版找不到CMPRx的定义!
EvaRegs.CMPR1 = 0x0C00;
EvaRegs.CMPR2 = 0x3C00;
EvaRegs.CMPR3 = 0xFC00;
//########################################################################
// EvbRegs.ACTRB.all = 0x0666;
// output pin 1 CMPR4 - active high 输出引脚1(CMPR4)-高电平有效 (P325)
// output pin 2 CMPR4 - active low 输出引脚2(CMPR4)-低电平有效
// output pin 3 CMPR5 - active high 输出引脚3(CMPR5)-高电平有效
// output pin 4 CMPR5 - active low 输出引脚4(CMPR5)-低电平有效
// output pin 5 CMPR6 - active high 输出引脚5(CMPR6)-高电平有效
// output pin 6 CMPR6 - active low 输出引脚6(CMPR6)-低电平有效 // EvbRegs.DBTCONB.all = 0x0000; // Disable deadband 禁止死区 (P331)
// EvbRegs.COMCONB.all = 0xA600;
//########################################################################
// Compare action control. Action that takes place 比较器方式控制。
// on a cmpare event 开事件比较器
EvaRegs.ACTRA.all = 0x0666;
// output pin 1 CMPR1 - active high 输出引脚1(CMPR1)-高电平有效 (P324)
// output pin 2 CMPR1 - active low 输出引脚2(CMPR1)-低电平有效
// output pin 3 CMPR2 - active high 输出引脚3(CMPR2)-高电平有效
// output pin 4 CMPR2 - active low 输出引脚4(CMPR2)-低电平有效
// output pin 5 CMPR3 - active high 输出引脚5(CMPR3)-高电平有效
// output pin 6 CMPR3 - active low 输出引脚6(CMPR3)-低电平有效
EvaRegs.DBTCONA.all = 0x0000; // Disable deadband 禁止死区 (P331)
EvaRegs.COMCONA.all = 0xA600;
// COMCONA[15]=CENABLE=1,使能比较操作。 (P319)
// COMCONA[14:13]=CLD1-0=01 B,当T1CNT=0 或T1CNT=T1PR (即下溢中断或周期匹配)
// COMCONA[12]=SVENABLE=0,禁止空间向量PWM模式。
// COMCONA[11:10]=ACTRLD1-0=01 B,当T1CNT=0或T1CNT=T1PR(即下溢或周期匹配)时,
// 控制寄存器重载
// COMCONA[9]=FCMPOE=1, 全比较输出使能,PWM1/2/3/4/5/6由相应比较逻辑驱动。
// COMCONA[8]=PDPINTA=0, 该位反映PDPINTA引脚的状态。
// COMCONA[7]=PCMP3OE=0,全比较3输出,PWM5/6处于高阻。
// COMCONA[6]=PCMP2OE=0,全比较2输出,PWM3/4处于高阻。
// COMCONA[5]=PCMP1OE=0,全比较1输出,PWM1/2处于高阻。
// COMCONA[4:3]=Reserve
// COMCONA[2]=C3TRIPE=0, 禁止C3TRIP。C3TRIP不影响比较输出3、COMCONA[8]或
// PDPINT标志位(EVAIFRA[0])。
// COMCONA[1]=C2TRIPE=0, 禁止C2TRIP。C2TRIP不影响比较输出2、COMCONA[7]或
// PDPINT标志位(EVAIFRA[0])。
// COMCONA[0]=C1TRIPE=0, 禁止C1TRIP。C1TRIP不影响比较输出1、COMCONA[6]或
// PDPINT标志位(EVAIFRA[0])。
}
/*******************************************************************************************
函数名称: init_evb()
函数功能: EVB配置T1PWM, T2PWM, PWM1-PWM6 ,初始化定时器
*******************************************************************************************/
void init_evb()
{
// 初始化EVB定时器3
// 定时器3控制T3PWM及PWM7-12
EvbRegs.T3PR = 0xFFFF; // 定时器3周期设置 (P313)
EvbRegs.T3CMPR = 0x3C00; // 定时器3比较器设置
EvbRegs.T3CNT = 0x0000; // 定时器3计数器设置
EvbRegs.T3CON.all = 0x1042;
// T3CON[15]=Free=0, 与Soft合用。一旦仿真挂起,立即停止。 (P314)
// T3CON[14]=Soft=0,
// T3CON[13]=Reserved, 保留
// T3CON[12:11]=TMODE1=10 B, 连续递增模式。,
// T3CON[10:8]=TPS2-0=000 B, 不分频,输入时钟频率同CPU时钟频率。
// T3CON[7]=T2SWT1/T4SWT3=0, T2SWT1对应EVA,使枚ㄊ逼?的使能位启动定时器1,
// T4SWT1对应EVB,使用定时器4的使能位启动定时器3。
// 使用自身的使能位。
// T3CON[6]=TENABLE=1, 定时器使能。
// T3CON[5:4]=TCLK1-0=00 B, 采用内部高速外设时钟(HSPCLK)
// T3CON[3:2]=TCLD1-0=00 B, 当计数器为0时,定时器比较寄存器重载。
// T3CON[1]=TECMPR=1, 定时器比较使能
// T3CON[0]=SELT1PR/SELT3PR=0,选用自身周期寄存器。
// 初始化EVB定时器4
// 定时器4控制T4PWM
EvbRegs.T4PR = 0x00FF; // 定时器4周期设置 (P313)
EvbRegs.T4CMPR = 0x0030; // 定时器4比较器设置 (P313)
EvbRegs.T4CNT = 0x0000; // 定时器4计数器设置 (P313)
EvbRegs.T4CON.all = 0x1042;
// T4CON[15]=Free=0, 与Soft合用。一旦仿真挂起,立即停止。
// T4CON[14]=Soft=0,
// T4CON[13]=Reserved, 保留
// T4CON[12:11]=TMODE1=10 B, 连续递增模式。,
// T4CON[10:8]=TPS2-0=000 B, 不分频,输入时钟频率同CPU时钟频率。
// T4CON[7]=T2SWT1/T4SWT3=0, T2SWT1对应EVA,使用定时器2的使能位启动定时器1,
// T4SWT1对应EVB,使用定时器4的使能位启动定时器3。
// 使用自身的使能位。
// T4CON[6]=TENABLE=1, 定时器使能。
// T4CON[5:4]=TCLK1-0=00 B, 采用内部高速外设时钟(HSPCLK)
// T4CON[3:2]=TCLD1-0=00 B, 当计数器为0时,定时器比较寄存器重载。
// T4CON[1]=TECMPR=1, 定时器比较使能
// T4CON[0]=SELT1PR/SELT3PR=0,选用自身周期寄存器
// 设置T3PWM及T4PWM
// 通过比较逻辑驱动T3/T4 PWM
EvbRegs.GPTCONB.bit.TCMPOE = 1;
// GTPCONB[6]=TCMPOE=1,通过比较逻辑驱动T3/T4 PWM (P318)
EvbRegs.GPTCONB.bit.T3PIN = 1;
// GPTCONB[1:0]=T3PIN = 01,GP定时器3比较器输出极性低电平有效。
EvbRegs.GPTCONB.bit.T4PIN = 2;
// GPTCONB[3:2]=T4PIN = 10,GP定时器4比较器输出极性高电平有效。
// 使能PWM7-PWM12的比较功能
EvbRegs.CMPR4 = 0x0C00;
EvbRegs.CMPR5 = 0x3C00;
EvbRegs.CMPR6 = 0xFC00;
// Compare action control. Action that takes place
// 比较器方式控制
// on a cmpare event 开事件比较器
EvbRegs.ACTRB.all = 0x0666;
// output pin 1 CMPR4 - active high 输出引脚1(CMPR4)-高电平有效 (P325)
// output pin 2 CMPR4 - active low 输出引脚2(CMPR4)-低电平有效
// output pin 3 CMPR5 - active high 输出引脚3(CMPR5)-高电平有效
// output pin 4 CMPR5 - active low 输出引脚4(CMPR5)-低电平有效
// output pin 5 CMPR6 - active high 输出引脚5(CMPR6)-高电平有效
// output pin 6 CMPR6 - active low 输出引脚6(CMPR6)-低电平有效
EvbRegs.DBTCONB.all = 0x0000; // Disable deadband 禁止死区 (P331)
EvbRegs.COMCONB.all = 0xA600;
// COMCONB[15]=CENABLE=1, 使能比较操作。 (P321)
// COMCONB[14:13]=CLD1-0=01 B, 当T3CNT=0 或T3CNT=T3PR (即下溢中断或周期匹配)
// COMCONB[12]=SVENABLE=0, 禁止空间向量PWM模式。
// COMCONB[11:10]=ACTRLD1-0=01 B,当T3CNT=0或T3CNT=T3PR(即下溢或周期匹配)时,
// 控制寄存器重载。
// COMCONB[9]=FCMPOE=1, 全比较输出使能,PWM1/2/3/4/5/6由相应比较逻辑驱动。
// COMCONB[8]=PDPINTA=0, 该位反映PDPINTA引脚的状态。
// COMCONB[7]=PCMP3OE=0, 全比较3输出,PWM5/6处于高阻。
// COMCONB[6]=PCMP2OE=0, 全比较2输出,PWM3/4处于高阻。
// COMCONB[5]=PCMP1OE=0, 全比较1输出,PWM1/2处于高阻。
// COMCONB[4:3]=Reserve
// COMCONB[2]=C3TRIPE=0, 禁止C3TRIP。C3TRIP不影响比较输出3、COMCONA[8]或
// PDPINT标志位(EVAIFRA[0])。
// COMCONB[1]=C2TRIPE=0,禁止C2TRIP。C2TRIP不影响比较输出2、COMCONA[7]或
// PDPINT标志位(EVAIFRA[0])。
// COMCONB[0]=C1TRIPE=0, 禁止C1TRIP。C1TRIP不影响比较输出1、COMCONA[6]或
// PDPINT标志位(EVAIFRA[0])。
}
/*******************************************************************************************
函数名称: delay(Uint16 dly)
函数功能: 延时函数
输入参数: 形参dly,dly越大延时越久
输出参数: 无
*******************************************************************************************/
void delay(Uint32 dly)
{
Uint32 i;
for(;dly>0;dly--)
for(i=0;i<500000;i++);
}
/*******************************************************************************************
函数名称: OscillographTable()
函数功能: 制作示波器表格
*******************************************************************************************/
void OscillographTable()
{
DashedLevel_n(14,1,250,2,9);
DashedLevel_n(15,1,250,2,1);
DashedLevel_n(16,1,250,2,1);
DashedLevel_n(113,1,250,2,1);
DashedLevel_n(115,1,250,2,1);
DashedLevel_n(213,1,250,2,1);
DashedLevel_n(215,1,250,2,1);
DashedVertical_n(12,14,195,2,11);
DashedVertical_n(13,14,195,2,1);
DashedVertical_n(14,14,195,2,1);
DashedVertical_n(136,14,195,2,1);
DashedVertical_n(138,14,195,2,1);
DashedVertical_n(260,14,195,2,1);
DashedVertical_n(261,14,195,2,1);
DrawaLevel(14,12,320,2);
DrawaLevel(215,12,320,2);
DrawaVertical(12,14,214,2);
DrawaVertical(262,14,214,2);
}
//******************************************************************************************
// 函数名称: adc_isr(void)
// 函数功能: ADC模块中断服务函数
//******************************************************************************************
interrupt void adc_isr(void)
{
Xram_pointer++;
if (Xram_pointer<0x11) // 存16组模数转换
{
AdcResultCopy((Uint16 *) 0x7108, (Uint16 *)0x13eff0+16*Xram_pointer,16);
// 将每组16个模数转换值存入起始地址为0x13f000对应外存空间,共有16组
// 256个数据。
// 第一次调用该程序时,Xram_pointer=1,故0x13eff0+16*Xram_pointer=0x13f000。
AdcRegs.ADCTRL2.bit.RST_SEQ1 = 1; // 复位SEQ1
AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1; // 清除INT SEQ1 bit
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; // 应答PIE 中断
}
else
{
Xram_pointer=0; // 初始化外存(存储组)跟踪指针
AdcRegs.ADCTRL2.bit.RST_SEQ1 = 1; // 复位SEQ1
AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1; // 清除INT SEQ1 bit
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; // 应答PIE 中断
}
}
/*******************************************************************************************
函数名称: VoltageCurve()
函数功能: 在液晶屏上制作电压曲线
*******************************************************************************************/
void VoltageCurve()
{
Uint16 i;
Uint16 x1,x2,y1,y2;
Xaddr=(Uint16 *)0x13f000;
for(i=0;i<250;i++)
{
x1=12+i;
x2=13+i;
y1=(114+(int)(100/2))-(int)(((int)(*(Xaddr+i)/20.475))/2);
y2=(114+(int)(100/2))-(int)(((int)(*(Xaddr+i+1)/20.475))/2);
if(y1!=y2) {liner(x1,y1,x1,y2,1);}
else { liner(x1,y1,x2,y2,1);}
//dot(12+i,215-(int)(*Xaddr++/20.475),1);
//dot(12+i,(114+(int)(100/2))-(int)(((int)(*Xaddr++/20.475))/2),1); //328 2
}
}
/*******************************************************************************************
函数名称: AdcResultCopy()
函数功能: 这个函数的原型为MemCopy()函数,仅仅作了右移4位及起始地址跟踪的变异。其功能
为将内存起始地址(AdcResultAddr)开始的连续number个寄存器中的数据顺序拷贝到始
地址为AdcObjectXram的外存对应单元中。
输入参数: 第一形参AdcResultAddr为一个指针变量,指向Adc结果寄存器某一地址。实参固定为
0x7108,即模数转换结果首地址。
第二形参AdcObjectXram,为存入外存的起始地址。实际使用时为动态值,
由变量Avg_pointer确定偏移量,前后两者相差16,以便有序存入下一组16个模数转换
结果。
第三形参number为拷贝到外存的数据的个数。
输出参数: 无
*******************************************************************************************/
void AdcResultCopy(Uint16 *AdcResultAddr, Uint16 *AdcObjectXram,Uint16 number)
{
Uint16 i;
for(i=0;i
>4;
// (*AdcResultAddr++)>>4的含义为: 取出某一个Adc
// 结果寄存器的数据右移4位后地址加1。
}
}
//================================================================================
// No more.
//================================================================================
二、事件管理器管理通用目的(GP)定时器示例程序 文 件: EvTimerPeriod.c
标 题: DSP281x 事件管理器管理通用目的(GP)定时器示例程序
条 件: 本程序需要DSP281x V1.00头文件支持,另外需配置成"boot to H0"操作方式。除了boot方式引
脚配置外,无需其他硬件配置方式。
说 明: 本程序设置EVA定时器1,EVA定时器2,EVB定时器3及EVB定时器4 触发周期溢出中断。
每完成一次中断服务程序计数器纪录一次。
EVA定时器1周期最短而EVB定时器4周期最长。
观察变量: EvaTimer1InterruptCount; EVA定时器1中断计数器
EvaTimer2InterruptCount; EVA定时器2中断计数器
EvbTimer3InterruptCount; EVB定时器3中断计数器
EvbTimer4InterruptCount; EVB定时器4中断计数器
另外在以下两个方面对TI提供的驱动源码进行了硬件和软件的增强:
(1) 增加了LED数码管显示的硬件接口。以便将EvPwm发生的次数反映在LED数码管上。
(2) 在更新EvPwm时,增加了受GPIO A控制的16个Led发光二极管的闪烁显示。 *******************************************************************************************/
#include "DSP281x_Device.h" // DSP281x 头文件包含文件
#include "DSP281x_Examples.h" // DSP281x 示例包含文件
// 本文件建立的函数原型声明。
interrupt void eva_timer1_isr(void); // 事件A定时器1中断服务函数 interrupt void eva_timer2_isr(void); // 事件A定时器2中断服务函数 interrupt void evb_timer3_isr(void); // 事件B定时器3中断服务函数 interrupt void evb_timer4_isr(void); // 事件B定时器4中断服务函数 void init_eva_timer1(void); // 事件A定时器1初始化函数
void init_eva_timer2(void); // 事件A定时器2初始化函数 void init_evb_timer3(void); // 事件B定时器3初始化函数
void init_evb_timer4(void); // 事件B定时器4初始化函数
void delay(); // 延时函数
void LedD_Display(void);
// 将模数转换值以10进制形式,在Led第4,3,2,1位数码管上进行显示 void LedH_Display(void);
// 将模数转换值以16进制两个字节形式,在Led第8,7,6,5位数码管上进行显示
// 用于本例的全局计数器
Uint32 EvaTimer1InterruptCount;
Uint32 EvaTimer2InterruptCount;
Uint32 EvbTimer3InterruptCount;
Uint32 EvbTimer4InterruptCount;
Uint32 count; // 供数码管显示用
void main(void)
{
// 步骤1 系统控制初始化: 锁相环(PLL),看门狗(WatchDog)及外设时钟
// (PeripheralClocks)初始化。该函数在DSP281x_SysCtrl.c文件中建立。
InitSysCtrl();
// 步骤2.初始化GPIO:
// 这个函数例举怎样将GPIO设置成其默认状态,该函数由DSP281x_Gpio.c文件建立。
// InitGpio(); // 本例跳过这个函数
// 步骤3 关所有中断并初始化PWM矢量表
DINT; // 关CPU中断
InitPieCtrl(); // 初始化PIE控制寄存器为默认状态。该状态关所有PIE中断并清除所
// 有标识。该函数在DSP281x_PieCtrl.c文件中建立。
IER = 0x0000; // 关CPU中断并清CPU中断标识。
IFR = 0x0000;
InitPieVectTable();
// 初始化PIE向量表,该向量表指出中断服务程序(ISR)的构架。即使在本范例中
// 没有用到中断,仍旧组装整张表。它在程序调试时是很有用的。ISR程序构架由
// DSP281x_DefaultIsr.c文件建立
// InitPieVectTable()函数由DSP281x_PieVect.c文件建立
EALLOW; // 允许访问受保护的寄存器
GpioMuxRegs.GPAMUX.all=0x0000; // 将A端口设置成IO方式
GpioMuxRegs.GPADIR.all=0xffff; // 将GPIO A所有15个端口配置成数字量输出
EDIS; // 禁止访问受保护的寄存器
GpioDataRegs.GPADAT.all=0xAAAA; // 间隔一个点亮LED发光二极管。
// 本例要用到的中断重新映射到由本文件建立的ISR函数。
//******************************************************************************************
// 关于 "PieVectTable.T1PINT = &eva_timer1_isr;" 指令的说明 // 1. eva_timer1_isr 是一个事件A定时器中断服务程序(ISR)。
// 2. 这个中断程序与中断扩展(PIE)向量表第2组INT2.4第4个中断向量T1PINT(EV-A) 定时器1中断// 对应。
// 3. 为了使这个程序响应对应的中断,还需作如下配置:
// PieCtrlRegs.PIEIER2.all = M_INT4;; // 使能 PIE 第2组 第4个T1PINT中断 // IER |= M_INT4; // 使能PIE向量表第2组T1PINT中断 // 这几条指令在本程序的后续指令中可以找到。这样,在发生T1PINT中断的情况下,将执行 // eva_timer1_isr()中断服务程序。
// "PieVectTable.T1PINT = &eva_timer1_isr;" 指令实际上就是通知编译器,在发生T1PINT中断的 // 情况下,将执行eva_timer1_isr()中断服务程序。eva_timer1_isr头上的"&"为取地址运算符。 //******************************************************************************************
EALLOW; //允许访问受保护的寄存器
PieVectTable.T1PINT = &eva_timer1_isr;
PieVectTable.T2PINT = &eva_timer2_isr;
PieVectTable.T3PINT = &evb_timer3_isr;
PieVectTable.T4PINT = &evb_timer4_isr;
EDIS; //禁止访问受保护的寄存器
// 步骤4 初始化器件所有外设: 这个函数由DSP281x_InitPeripherals.c文件建立。
//InitPeripherals(); // 本例不需要这个函数
init_eva_timer1();
init_eva_timer2();
init_evb_timer3();
init_evb_timer4();
// 步骤5. 用户代码,中断使能:
EvaTimer1InterruptCount = 0; // 初始化计数器值为0
EvaTimer2InterruptCount = 0;
EvbTimer3InterruptCount = 0;
EvbTimer4InterruptCount = 0;
PieCtrlRegs.PIEIER2.all = M_INT4; // 使能PIE第2组中断4 T1PINT (定义M_INT4=0x0008)
PieCtrlRegs.PIEIER3.all = M_INT1; // 使能PIE第3组中断1 T2PINT (定义M_INT1=0x0001)
PieCtrlRegs.PIEIER4.all = M_INT4; // 使能PIE第4组中断4 T3PINT
PieCtrlRegs.PIEIER5.all = M_INT1; // 使能PIE第5组中断1 T4PINT
IER |= (M_INT2 | M_INT3 | M_INT4 | M_INT5);
// 使能CPU中断INT2的T1PINT,INT3的T2PINT,INT4的T3PINT以及INT5的T4PINT。
// Enable global Interrupts and higher priority real-time debug events:
EINT; // 使能全局中断 INTM
ERTM; // 使能全局实时中断 DBGM
// 步骤6. 空循环。 IDLE loop. Just sit and loop forever:
for(;;);
}
/*******************************************************************************************
函数名称: init_eva_timer1(void)
函数功能: 事件A定时器1初始化函数
*******************************************************************************************/
void init_eva_timer1(void)
{
// 初始化EVA 定时器1.设置定时器1 寄存器 (EV A).
EvaRegs.GPTCONA.all = 0;
// Set the Period for the GP timer 1 to 0x0200;
EvaRegs.T1PR = 0x0200; // 设置GP定时器1周期为0x0200。 (P313)
EvaRegs.T1CMPR = 0x0000; // 设置GP定时器1比较寄存器值为0。 (P313)
// Count up, x128, internal clk, enable compare, use own period
EvaRegs.EVAIMRA.bit.T1PINT = 1;
// EVAIMRA[7]=T1PINT = 1,使能GP定时器1周期中断 (P335)
EvaRegs.EVAIFRA.bit.T1PINT = 1;
// EVAIFRA[7]=T1PINT = 1,复位GP定时器1周期中断标志位 (P332)
// EVA中断标志寄存器A(EVAIFRA)的各标志位与EVA中断屏蔽寄存器A(EVAIMRA)
// 各屏蔽位是一一对应的。当中断被屏蔽时,可检测相应位来判断是否发生中断。
EvaRegs.T1CNT = 0x0000; // 清空GP定时器1计数器 (P313)
EvaRegs.T1CON.all = 0x1742;
// T1CON[15]=Free=0,与Soft合用。一旦仿真挂起,立即停止。 (P314)
// T1CON[14]=Soft=0,
// T1CON[13]=Reserved,保留
// T1CON[12:11]=TMODE1=10 B,连续递增模式。,
// T1CON[10:8]=TPS2-0=111 B,输入时钟频率是CPU时钟频率的128分频。
// T1CON[7]=T2SWT1/T4SWT3=0,T2SWT1对应EVA,使用定时器2的使能位启动定时器1,
// T4SWT1对应EVB,使用定时器4的使能位启动定时器3。
// 使用自身的使能位。
// T1CON[6]=TENABLE=1,定时器使能
// T1CON[5:4]=TCLK1-0=00 B,采用内部高速外设时钟(HSPCLK)
// T1CON[3:2]=TCLD1-0=00 B,当计数器为0时,定时器比较寄存器重载。
// T1CON[1]=TECMPR=1,定时器比较使能
// T1CON[0]=SELT1PR/SELT3PR=0,选用自身周期寄存器。
EvaRegs.GPTCONA.bit.T1TOADC = 2;
// GPTCONA[8:7]=T1TOADC =10 B,开定时器1周期中断启动EVA 模数转换(ADC) (P315) }
/*******************************************************************************************
函数名称: init_eva_timer2(void)
函数功能: 事件A定时器2初始化函数
*******************************************************************************************/
void init_eva_timer2(void)
{
// 初始化EVA 定时器2.设置定时器2 寄存器 (EV A).
EvaRegs.GPTCONA.all = 0;
EvaRegs.T2PR = 0x0400; // 设置GP定时器2周期为0x0400。 (P313)
EvaRegs.T2CMPR = 0x0000; // 设置GPㄊ逼?比较寄存器值为0。 (P313)
// Count up, x128, internal clk, enable compare, use own period
EvaRegs.EVAIMRB.bit.T2PINT = 1;
// EVAIMRB[0]=T2PINT = 1,使能GP定时器2周期中断 (P336)
EvaRegs.EVAIFRB.bit.T2PINT = 1;
// EVAIFRB[0]=T2PINT = 1,复位GP定时器2周期中断标志位 (P334)
// EVA中断标志寄存器B(EVAIFRB)的各标志位与EVA中断屏蔽寄存器B(EVAIMRB)
// 各屏蔽位是一一对应的。当中断被屏蔽时,可检测相应位来判断是否发生中断。
EvaRegs.T2CNT = 0x0000; // 清空GP定时器2计数器 (P313)
EvaRegs.T2CON.all = 0x1742;
// T2CON[15]=Free=0,与Soft合用。一旦仿真挂起,立即停止。 (P314)
// T2CON[14]=Soft=0,
// T2CON[13]=Reserved,保留
// T2CON[12:11]=TMODE1=10 B,连续递增模式。,
// T2CON[10:8]=TPS2-0=111 B,输入时钟频率是CPU时钟频率的128分频。
// T2CON[7]=T2SWT1/T4SWT3=0,T2SWT1对应EVA,使用定时器2的使能位启动定时器1,
// T4SWT1对应EVB,使用定时器4的使能位启动定时器3。
// 使用自身的使能位。
// T2CON[6]=TENABLE=1, 定时器使能。
// T2CON[5:4]=TCLK1-0=00 B,采用内部高速外设时钟(HSPCLK)
// T2CON[3:2]=TCLD1-0=00 B,当计数器为0时,定时器比较寄存器重载。
// T2CON[1]=TECMPR=1,定时器比较使能
// T2CON[0]=SELT1PR/SELT3PR=0,选用自身周期寄存器。
EvaRegs.GPTCONA.bit.T2TOADC = 2;
// GPTCONA[10:9]=T2TOADC =10 B,开定时器2周期中断启动EVA 模数转换(ADC) }
/*******************************************************************************************
函数名称: init_evb_timer3(void)
函数功能: 事件B定时器3初始化函数
*******************************************************************************************/
void init_evb_timer3(void)
{
// 初始化EVB 定时器3.设置定时器3 寄存器 (EV B).
EvbRegs.GPTCONB.all = 0;
EvbRegs.T3PR = 0x0800; // 设置GP定时器3周期为0x0200。 (P313)
EvbRegs.T3CMPR = 0x0000; // 设置GP定时器3比较寄存器值为0。 (P313)
// Enable Period interrupt bits for GP timer 3
// Count up, x128, internal clk, enable compare, use own period
EvbRegs.EVBIMRA.bit.T3PINT = 1;
// EVBIMRA[7]=T3PINT = 1,使能GP定时器3周期中断 (P340)
EvbRegs.EVBIFRA.bit.T3PINT = 1;
// EVBIFRB[7]=T3PINT = 1,复位GP定时器3周期中断标志位 (P337)
// EVB中断标志寄存器A(EVBIFRA)的各标志位与EVB中断屏蔽寄存器A(EVBIMRA)
// 各屏蔽位是一一对应的。当中断被屏蔽时,可检测相应位来判断是否发生中断。
EvbRegs.T3CNT = 0x0000; // 清空GP定时器3计数器 (P313)
EvbRegs.T3CON.all = 0x1742;
// T3CON[15]=Free=0,与Soft合用。一旦仿真挂起,立即停止。 (P314)
// T3CON[14]=Soft=0,
// T3CON[13]=Reserved,保留
// T3CON[12:11]=TMODE1=10 B,连续递增模式。,
// T3CON[10:8]=TPS2-0=111 B,输入时钟频率是CPU时钟频率的128分频。
// T3CON[7]=T2SWT1/T4SWT3=0,T2SWT1对应EVA,使用定时器2的使能位启动定时器1,
// T4SWT1对应EVB,使用定时器4的使能位启动定时器3。
// 使用自身的使能位。
// T3CON[6]=TENABLE=1, 定时器使能。
// T3CON[5:4]=TCLK1-0=00 B,采用内部高速外设时钟(HSPCLK)
// T3CON[3:2]=TCLD1-0=00 B,当计数器为0时,定时器比较寄存器重载。
// T3CON[1]=TECMPR=1,定时器比较使能
// T3CON[0]=SELT1PR/SELT3PR=0,选用自身周期寄存器。
EvbRegs.GPTCONB.bit.T3TOADC = 2;
// GPTCONB[8:7]=T3TOADC=10 B,开定时器3周期中断启动EVA 模数转换(ADC) (P318) }
/*******************************************************************************************
函数名称: init_evb_timer4(void)
函数功能: 事件B定时器4初始化函数
*******************************************************************************************/
void init_evb_timer4(void)
{
// 初始化EVB 定时器4.设置定时器4 寄存器 (EV B).
EvbRegs.GPTCONB.all = 0;
EvbRegs.T4PR = 0x1000; // 设置GP定时器4周期为0x1000。 (P313)
EvbRegs.T4CMPR = 0x0000; // 设置GP定时器4比较寄存器值为0。 (P313)
// Count up, x128, internal clk, enable compare, use own period
EvbRegs.EVBIMRB.bit.T4PINT = 1;
// EVBIMRB[0]=T4PINT = 1,使能GP定时器4周期中断 (P341)
EvbRegs.EVBIFRB.bit.T4PINT = 1;
// EVBIFRB[0]=T3PINT = 1,复位GP定时器4周期中断标志位 (P339)
// EVB中断标志寄存器B(EVBIFRB)的各标志位与EVB中断屏蔽寄存器B(EVBIMRB)
// 各屏蔽位是一一对应的。当中断被屏蔽时,可检测相应位来判断是否发生中断。
EvbRegs.T4CNT = 0x0000; // 清空GP定时器4计数器 (P313)
EvbRegs.T4CON.all = 0x1742;
// T4CON[15]=Free=0,与Soft合用。一旦仿真挂起,立即停止。 (P314)
// T4CON[14]=Soft=0,
// T4CON[13]=Reserved,保留
// T4CON[12:11]=TMODE1=10 B,连续递增模式。,
// T4CON[10:8]=TPS2-0=111 B,输入时钟频率是CPU时钟频率的128分频。
// T4CON[7]=T2SWT1/T4SWT3=0,T2SWT1对应EVA,使用定时器2的使能位启动定时器1,
// T4SWT1对应EVB,使用定时器4的使能位启动定时器3。
// 使用自身的使能位。
// T4CON[6]=TENABLE=1, 定时器使能。
// T4CON[5:4]=TCLK1-0=00 B,采用内部高速外设时钟(HSPCLK)
// T4CON[3:2]=TCLD1-0=00 B,当计数器为0时,定时器比较寄存器重载。
// T4CON[1]=TECMPR=1,定时器比较使能
// T4CON[0]=SELT1PR/SELT3PR=0,选用自身周期寄存器。
EvbRegs.GPTCONB.bit.T4TOADC = 2;
// GPTCONB[10:9]=T4TOADC=10 B,开定时器4周期中断启动EVA 模数转换(ADC) (P318) }
/*******************************************************************************************
函数名称: eva_timer1_isr(void)
函数功能: 事件A定时器1中断服务函数
*******************************************************************************************/
interrupt void eva_timer1_isr(void)
{
if(EvaTimer1InterruptCount>9999) EvaTimer1InterruptCount=0;
EvaTimer1InterruptCount++;
count=EvaTimer1InterruptCount;
LedD_Display(); // 以十进制形式在右边的4个数码管显示count数值。
LedH_Display(); // 以十六进制形式在左边的4个数码管显示count数值。
GpioDataRegs.GPATOGGLE.all = 0xffff; // A端口取反
delay(5);
EvaRegs.EVAIMRA.bit.T1PINT = 1;
// EVAIMRA[7]=T1PINT=1,使能此后的GP定时器1周期中断。 (P335)
EvaRegs.EVAIFRA.all = BIT7;
// 注意: 为安全起见,采用一个位掩码来写整个EVAIFRA寄存器。写一位将会引起 (P332)
// 一个读-修改-写操作,可能造成写1会清除其他位。
// 这里的 BIT7 是一个掩码,由头文件 DSP281x_Device.h 中的指令
// "#define BIT7 0x0080" 定义。实际上就是置 T1PINT FLAG=1,复位标志位。
// 如果屏蔽这条指令,即不复位标志位,任其保持1状态,则此后将不会产生定时
// 器1周期中断。
PieCtrlRegs.PIEACK.all = PIEACK_GROUP2;
// 中断应答以便接收此后 PIE 第2组的中断。 (P185)
// 这里的 PIEACK_GROUP2 是一个掩码,由头文件 DSP281x_PieCtrl.h 中的指令
// "#define PIEACK_GROUP2 0x0002;" 定义。
}
/*******************************************************************************************
函数名称: eva_timer2_isr(void)
函数功能: 事件A定时器2中断服务函数
*******************************************************************************************/
interrupt void eva_timer2_isr(void)
{
EvaTimer2InterruptCount++;
EvaRegs.EVAIMRB.bit.T2PINT = 1;
// EVAIMRB[0]=T2PINT = 1,使能此后的GP定时器2周期中断。 (P336)
EvaRegs.EVAIFRB.all = BIT0;
// 注意: 为安全起见,采用一个位掩码来写整个EVAIFRB寄存器。写一位将会引起 (P334)
// 一个读-修改-写操作,可能造成写1会清除其他位。
// 这里的 BIT0 是一个掩码,由头文件 DSP281x_Device.h 中的指令
// "#define BIT0 0x0001" 定义。实际上就是置 T2PINT FLAG=1,复位标志位。
// 如果屏蔽这条指令,即不复位标志位,任其保持1状态,则此后将不会产生定时
// 器2周期中断。
PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;
// 中断应答以便接收此后 PIE 第3组的中断。 (P185)
// 这里的 PIEACK_GROUP3 是一个掩码,由头文件 DSP281x_PieCtrl.h 中的指令
// "#define PIEACK_GROUP3 0x0004;" 定义。
}
/*******************************************************************************************
函数名称: evb_timer3_isr(void)
函数功能: 事件B定时器3中断服务函数
*******************************************************************************************/
interrupt void evb_timer3_isr(void)
{
EvbTimer3InterruptCount++;
EvbRegs.EVBIFRA.all = BIT7;
// 注意: 为安全起见,采用一个位掩码来写整个EVBIFRA寄存器。写一位将会引起 (P337)
// 一个读-修改-写操作,可能造成写1会清除其他位。
// 这里的 BIT7 是一个掩码,由头文件 DSP281x_Device.h 中的指令
// "#define BIT7 0x0080" 定义。实际上就是置 T3PINT FLAG=1,复位标志位。
// 如果屏蔽这条指令,即不复位标志位,任其保持1状态,则此后将不会产生定时
// 器3周期中断。
// Acknowledge interrupt to receive more interrupts from PIE group 4
PieCtrlRegs.PIEACK.all = PIEACK_GROUP4;
// 中断应答以便接收此后 PIE 第4组的中断。 (P185)
// 这里的 PIEACK_GROUP4 是一个掩码,由头文件 DSP281x_PieCtrl.h 中的指令
// "#define PIEACK_GROUP4 0x0008;" 定义。
}
/*******************************************************************************************
函数名称: evb_timer4_isr(void)
函数功能: 事件B定时器4中断服务函数
*******************************************************************************************/
interrupt void evb_timer4_isr(void)
{
EvbTimer4InterruptCount++;
// Note: To be safe, use a mask value to write to the entire
// EVBIFRB register. Writing to one bit will cause a read-modify-write
// operation that may have the result of writing 1's to clear
// bits other then those intended.
EvbRegs.EVBIFRB.all = BIT0;
// 注意: 为安全起见,采用一个位掩码来写整个EVBIFRB寄存器。写一位将会引起 (P339)
// 一个读-修改-写操作,可能造成写1会清除其他位。
// 这里的 BIT0 是一个掩码,由头文件 DSP281x_Device.h 中的指令
// "#define BIT0 0x0001;" 定义。实际上就是置 T4PINT FLAG=1,复位标志位。
// 如果屏蔽这条指令,即不复位标志位,任其保持1状态,则此后将不会产生定时
// 器4周期中断。
// Acknowledge interrupt to receive more interrupts from PIE group 5
PieCtrlRegs.PIEACK.all = PIEACK_GROUP5;
// 中断应答以便接收此后 PIE 第5组的中断。 (P185)
// 这里的 PIEACK_GROUP5 是一个掩码,由头文件 DSP281x_PieCtrl.h 中的指令
// "#define PIEACK_GROUP5 0x0010;" 定义。
}
/*******************************************************************************************
函数名称: delay(Uint16 dly)
函数功能: 延时函数
输入参数: 形参dly,dly越大延时越久
输出参数: 无
*******************************************************************************************/ void delay(Uint32 dly)
{
Uint32 i;
for(;dly>0;dly--)
for(i=0;i<500000;i++);
}
//================================================================================ // No more.
//================================================================================
实验7 Xram实验
文件: Xram.c
条件: 本程序需要DSP281x V1.00头文件支持,另外还需配置成"boot to H0"操作方式。本例使用液晶
屏显示存储区0x13f000-0x13f02b中的一块数据。由于液晶屏是一个低速扩展外设,因此,须将
InitSysCtrl()函数中的PLLCR 设置成0x05(),这个函数位于DSP281x_SysCtrl.c文件中。 *******************************************************************************************/
#include "DSP281x_Device.h" // DSP281x头文件包含文件
#include "DSP281x_Examples.h" // DSP281x范例包含文件
/***** 注意!有关液晶屏显示的函数原型声明都放在 DSP281x_GlobalPrototypes.h 文件中 *****
// 函数原型声明,以下4个函数来自本文件。
void CheckXram();
// 初始化外存起始地址到结束地址所有存储单元的数据为0
void WriteXram();
// 从指定的外存地址StartAddr开始到EndAddr结束,顺序写入count数据。 void MoveRam();
// 将存储区地址 Addr1-(Addr1+number) 中的数据拷贝到 Addr2-(Addr2+number) 中的
// 对应单元
void delay(Uint16 dly);
// 延时函数
// 函数原型声明,以下2个函数来自Bc7281.c文件。
void LedH_Display();
// 将模数转换值以16进制形式,在Led第4,3,2,1位数码管上显示。 void LedD_Display();
// 将模数转换值以10进制形式,在Led第8,7,6,5位数码管上显示。 void error(void);
//*****
//extern Uint16 RamfuncsLoadStart; //extern Uint16 RamfuncsLoadEnd;
//extern Uint16 RamfuncsRunStart;
//*****
// 全局变量声明
Uint16 count=0;
void main()
{
// 步骤1 系统控制初始化:
InitSysCtrl(); // 锁相环(PLL),看门狗(WatchDog)及外设时钟(PeripheralClocks)初始化。
// 这个函数由DSP281x_SysCtrl.c文件建立。
// 步骤2。初始化GPIO
// InitGpio()函数例举怎样将GPIO设置成其默认状态,该函数由DSP281x_Gpio.c文件建立。
//InitGpio(); // 本例跳过这个函数。
// 步骤3 关所有中断并初始化PIE向量表:
DINT; // 关CPU中断。
//InitPieCtrl(); // 初始化PIE控制寄存器为默认状态,该状态关所有PIE中断并清所有
// PIE中断标识符。 InitPieCtrl()函数由DSP281x_PieCtrl.c文件建立。
// 本例跳过这个函数。
IER = 0x0000;
IFR = 0x0000; // 关CPU中断并清所有CPU中断标识符。
//InitPieVectTable();
// 初始化PIE向量表,该向量表指明了中断服务程序(ISR)的一种构架。
// 即使在这个示例中用不到中断,仍板上组装了整个PIE向量表。作为调试
// 目的这是很有用的。ISR程序架构由DSP281x_DefaultIsr.c文件建立。
// InitPieVectTable()函数由DSP281x_PieVect.c文件建立。
// 本例跳过这个函数。
// 步骤4 初始化器件外设:
//InitPeripherals();
// 这个函数由DSP281x_InitPeripherals.c文件建立。
// 本例不跳过这个函数。
//InitXintf(); // 这个函数将扩展接口初始化为系统默认复位状态。本例跳过这个函数。 //*****
// MemCopy(&RamfuncsLoadStart, &RamfuncsLoadEnd, &RamfuncsRunStart);
// Call Flash Initialization to setup flash waitstates
// This function must reside in RAM // InitFlash();
//*****
// 步骤5 用户代码
lcd_init(); // Lcd 初始化
clearscr1(); // 清除第一显示缓冲区:0x0000-0x29ff
clearscr2(); // 清除第二显示缓冲区:0x2a00-0x53ff
clearscr3(); // 清除第三显示缓冲区:0x5400-0x7FFF
Disp_XramTab();
CheckXram((Uint16 *)0x130000,(Uint16 *)0x13ffff);
// 检查始地址0x130000到结束地址0x13ffff是否能正确存储。
// 若不能正确存储停止仿真。
// 无限循环
for(;;)
{
WriteXram((Uint16 *)0x13f000,44);
// 将16位count顺序递增数写入外存0x13f000-0x13f02b各单元。
//DispXram_D((Uint16 *) 0x13F000);
// 在液晶屏上以10进制显示存储区0x13f000-0x13f02b中的一块数据。
DispXram_H((Uint16 *) 0x13F000);
// 在液晶屏上以16进制显示存储区0x13f000-0x13f02b中的一块数据。
LedH_Display((Uint16 *)0x13f000);
// 在右边4个数码管上以16进制显示count(44倍率)动态基数值。
LedD_Display((Uint16 *)0x13f000);
// 在左边4个数码管上以10进制显示count(44倍率)动态基数值,删掉个位。
delay(10); // 长延时
}
}
/*******************************************************************************************
函数名称: CheckXram(Uint16 *StartAddr, Uint16 *EndAddr) 函数功能: 从指定的外存地址StartAddr开始到EndAddr结束,顺序写入count增量数据。并将刚写入
存储器的数据取出与count进行比较,若不等终止仿真。用于检查存储芯片工作是否正常。 输入参数: 第一形参StartAddr为一指针变量,要写入数据的首地址。
第二形参EndAddr为一指针变量,要写入数据的结束地址。
输出参数: 无
原 作: 任润柏
日 期: 2006.8
*******************************************************************************************/
void CheckXram(Uint16 *StartAddr, Uint16 *EndAddr) {
while(StartAddr0;dly--)
{
for(i=0;i<60000;i++);
}
}
void error(void)
{
asm(" ESTOP0"); // Test failed!! Stop!
for (;;);
}
//================================================================================
// No more.
//================================================================================
实验8 软件区分中断优先权实验
文 件: Example_281xSWPrioritizedInterrupts.c
标 题: DSP281x Software Prioritized Interrupt Example.
DSP281x 用软件区分中断优先权的例子
说 明: 本程序需DSP281x V1.00头文件支持,另外还需配置成"boot to H0"操作方式。
除了boot方式引脚配置外,不需其他的硬件配置。
功 能:
对于大多数应用软件而言,在PIE模式下用硬件区分中断优先权已经足够了。
作为一种应用,有必要通过软件方式来区分中断优先权,本例提供了一个如何通过软件区
分中断优先权的范例。
有关 F2810/12 中断优先权的更多的信息,可查阅包含本例的
ReadMe_Example_28xISRPriorities.pdf文件。
本例通过写PIEIFR寄存器模拟中断冲突,在同一时刻,它可模拟多次中断进入PIE模块。
通过由 DSP281x_SWPrioritizedIsrLevels.h 文件建立的软件中断服务程序优先权表来确定中断
服务程序优先权
1) 在编译之前,须在DSP281x_SWPrioritizedIsrLevels.h文件中设置全局中断优先权组。
2) 编译代码,加载并运行
3) 在每个程序测试段的末尾有一个断点代码(ESTOP0),当代码在断点处停止时,可检查
ISRTrace缓冲器以便观察ISR's完成的次序。所有PIE中断都加入到ISRTrace缓冲器中。ISRTrace
缓冲器由如下所示的16进制列表组成
0x00wx <- 首先完成 PIE第w组中断x
0x00yz <- 其次完成 PIE第y组中断z
4) 若需要的话,可重新设置全局中断优先权组并重复测试以观察变化。
观察变量: ISRTrace[50]
ISR's按序跟踪在每个程序测试段之后完成,可检查这个缓冲器以确定
ISR's是否按想要的次序完成中断。
//########################################################################### // Ver | dd mmm yyyy | Who | Description of changes
// ====|===========|======|============================================ // 1.00| 11 Sep 2003 | L.H. | Changes since previous version (v.58 Alpha) // | | | Corrected a number of comments. Re-structured // | | | the flow of each testcase to make more sense. //###########################################################################
#include "DSP281x_Device.h" // DSP281x Headerfile Include File #include "DSP281x_Examples.h" // DSP281x Examples Include File
// Define which interrupts are used in the PIE for each group. // 定义PIE每组可用的中断
#define ISRS_GROUP1 (M_INT1|M_INT2|M_INT4|M_INT5|M_INT6|M_INT7|M_INT8)
// ISRS_GROUP1=0xFB 定义第一组所有中断
#define ISRS_GROUP2 (M_INT1|M_INT2|M_INT3|M_INT4|M_INT5|M_INT6|M_INT7)
// ISRS_GROUP2=0x7F 定义第二组所有中断
#define ISRS_GROUP3 (M_INT1|M_INT2|M_INT3|M_INT4|M_INT5|M_INT6|M_INT7)
// ISRS_GROUP3=0x7F 定义第三组所有中断
#define ISRS_GROUP4 (M_INT1|M_INT2|M_INT3|M_INT4|M_INT5|M_INT6|M_INT7)
// ISRS_GROUP4=0x7F 定义第四组所有中断
#define ISRS_GROUP5 (M_INT1|M_INT2|M_INT3|M_INT4|M_INT5|M_INT6|M_INT7)
// ISRS_GROUP5=0x7F 定义第五组所有中断
#define ISRS_GROUP6 (M_INT1|M_INT2|M_INT5|M_INT6)
// ISRS_GROUP6=0x33 定义第六组所有中断
#define ISRS_GROUP9 (M_INT1|M_INT2|M_INT3|M_INT4|M_INT5)
// ISRS_GROUP9=0x1F 定义第九组除ECAN1INT(INT9.6)之外的所有中断
// (见P181)
// M_INT1=0x0001, M_INT2=0x0002, M_INT3=0x0004, M_INT4=0x0008
// M_INT5=0x0010, M_INT6=0x0020, M_INT7=0x0040, M_INT8=0x0080
// M_INT9=0x0100, M_INT10=0x0200,M_INT11=0x0400,M_INT12=0x0800
// M_INT13=0x1000,M_INT14=0x2000,M_DLOG=0x4000, M_RTOS=0x8000
void BC7281Init(void);
Uint16 count;
// This array will be used as a trace to check the order that the // interrupts were serviced
// 这个寄存器阵列用以跟踪查验中断服务程序执行的顺序
Uint16 ISRTrace[50];
Uint16 ISRTraceIndex; // used to update an element in the trace buffer
// 用以更新跟踪缓冲器中的元素
void main(void)
{
Uint16 i;
// Step 1. Initialize System Control:
// PLL, WatchDog, enable Peripheral Clocks
// This example function is found in the DSP281x_SysCtrl.c file.
InitSysCtrl();
// 初始化系统控制:PLL, WatchDog,使能外部时钟。
// InitSysCtrl()函数由DSP281x_SysCtrl.c建立
// Step 2. Initalize GPIO: GPIO初始化
// This example function is found in the DSP281x_Gpio.c file and // illustrates how to set the GPIO to it's default state. // 该函数由DSP281x_Gpio.c文件建立,InitGpio()函数阐明如何设置GPIO为默认
// 方式。
// InitGpio(); // Skipped for this example 本例跳过这个函数。
// Step 3. Clear all interrupts and initialize PIE vector table: // 清全局中断并初始化PIE向量表,
// Disable CPU interrupts 关CPU中断
DINT;
// Initialize PIE control registers to their default state. // 初始化PIE控制寄存器为默认方式。
// The default state is all PIE interrupts disabled and flags are cleared.
// 该方式关所有PIE中断并清所有标识符(flags)。
// This function is found in the DSP281x_PieCtrl.c file. // InitPieCtrl()函数由DSP281x_PieCtrl.c文件建立。
InitPieCtrl();
// PIE(Peripheral Interrupt Expansion block)外设中断扩展模块
// Disable CPU interrupts and clear all CPU interrupt flags: // 关CPU中断并清所有CPU中断标识符(flags)。
IER = 0x0000;
IFR = 0x0000;
// Initialize the PIE vector table with pointers to the shell Interrupt // Service Routines (ISR).
// 初始化PIE向量表,该向量在于指示中断服务程序(ISR)的框架。
// This will populate the entire table, even if the interrupt // is not used in this example. This is useful for debug purposes. // 即使在本程序用不到,PIE仍构建了一张全部中断向量表。这对程序调试是有用的。
// The shell ISR routines are found in DSP281x_DefaultIsr.c. // ISR程序由DSP281x_DefaultIsr.c文件建立。
// This function is found in DSP281x_PieVect.c.
// InitPieVectTable()函数由DSP281x_PieVect.c文件建立。
InitPieVectTable();
// Step 4. Initialize all the Device Peripherals: // 初始化所有外围器件,
// This function is found in DSP281x_InitPeripherals.c // InitPeripherals()函数由DSP281x_InitPeripherals.c文件建立
// InitPeripherals();
// Not required for this example 本程序不需要对外围器件初始化
// Step 5. User specific code, enable interrupts: // 应用代码,中断使能
// CASE 1:
// Force all group 1 interrupts at once by writing to the PIEIFR1 register
// 通过写PIEIFR1寄存器激活1组所有有效中断
// Prepare for the test: 准备测试
// Disable interrupts 禁止中断
// Clear the trace buffer, PIE Control Register, CPU IER and IFR registers
// 清跟踪缓冲器,PIE控制寄存器,CPU IER及IFR寄存器。
DINT;
for(i = 0; i < 50; i++) ISRTrace[i] = 0x00;
ISRTraceIndex = 0;
InitPieCtrl();
IER = 0;
IFR &= 0;
// Enable the PIE block
// 使能PIE模块
PieCtrlRegs.PIECRTL.bit.ENPIE = 1;
// PIE中断控制寄存器取回向量使能: ENPIE=PIECRTL[0]
// 当ENPIE=1,所有向量取自PIE向量表,PIE模块使能;
// 当ENPIE=0,PIE模块无效。 (见P185)
// Enable PIE group 1 interrupt 1-8
// 使能PIE 1-8组 1中断
PieCtrlRegs.PIEIER1.all = 0x00FF;
// PIE中断使能寄存器PIEIERx(x=1-12),高8位保留,低8位为:INTx.8-INTx.1
// 当INTx.y=1,使能中断服务;
// 当INTx.y=0,将使该位中断服务无效。
// PIEIER1 = 0x00FF,使能 PIE 1组 1-8中断
// Make sure PIEACK for group 1 is clear (default after reset)
// 确定PIEACK 1组已清0(复位后的默认值)
PieCtrlRegs.PIEACK.all = M_INT1; //(见P185)
// PIE中断应答寄存器 PIEACKx,如果在组中断里有一个中断是未处理的,
// 向各自的中断位写1,使PIE块驱动一个脉冲进入核中断输入。
// PIEACK=M_INT1=0x0001,使PIE块驱动一个脉冲进入INT1核中断输入。
// Enable CPU INT1
// 使能CPU INT1
IER |= M_INT1; //(见P57)
// CPU中断使能寄存器: IER[0]=INT1=1,CPU INT1中断使能(M_INT1=0x0001)。
// Force all valid interrupts for Group 1
// 使所有有效中断归入1组
PieCtrlRegs.PIEIFR1.all = ISRS_GROUP1; // ISRS_GROUP1=0x00FB (见P187)
// PIE 中断标志寄存器 PIEIFRx(x=1-12),PIE模块(INT1-INT12)
// 使用各个CPU中断中的一个.
// PIEIFRx寄存器高8位保留,低8位依次为: INTx.8-INTx.1当寄存器位置1,
// 激活对应中断. 当一个中断处理完毕或向该位写0时,该位清0.
// PIEIFR1=
// =ISRS_GROUP1=(M_INT1|M_INT2|M_INT4|M_INT5|M_INT6|M_INT7|M_INT8)
// 激活1组所有有效中断
// Enable global Interrupts CPU level:
// 使能CPU级全局中断
EINT; // Enable Global interrupt INTM 使能全局INTM中断
// Wait for all Group 1 interrupts to be serviced
// 等待1组所有中断的中断服务
while(PieCtrlRegs.PIEIFR1.all != 0x0000 ){}
// 当1组所有中断服务完毕,执行下面程序,否则等待
// Stop here and check the ISRTrace to determine which order the
// ISR Routines completed. The order is dependant on the priority
// assigned in the DSP281x_SWPrioritizedIsrLevels.h file
// 停止仿真,检查ISRTrace缓冲器,以便测定ISR中断服务程序完成的顺序。
// 该顺序由 DSP281x_SWPrioritizedIsrLevels.h 文件中的优先权配置决定
//
// The ISRTrace will contain a list of values corresponding to the
// interrupts serviced in the order they were serviced.
// ISRTrace包含一个列表值,该列表值与已发生的中断服务的顺序相对应
// For example if the ISRTrace looks like this
// 例如
// 0x0014 ISR Group 1 interrupt 4
// 0x0017 ISR Group 1 interrupt 7
// 0x0016 ISR Group 1 interrupt 6
// 0x0000 end of trace
//? asm(" ESTOP0"); // 插入汇编指令: ESTOP0(仿真停止0)
// CASE 2:
// Force all group 2 interrupts at once by writing to the PIEIFR2 register // 通过写PIEIFR2寄存器激活2组所有有效中断
// Prepare for the test: 准备测试
// Disable interrupts 禁止中断
// Clear the trace buffer, PIE Control Register, CPU IER and IFR registers
// 清跟踪缓冲器,PIE控制寄存器,CPU IER及IFR寄存器。
DINT; //关全局INTM中断
for(i = 0; i < 50; i++) ISRTrace[i] = 0;
ISRTraceIndex = 0;
InitPieCtrl();
IER = 0;
IFR &= 0;
// Enable the PIE block
PieCtrlRegs.PIECRTL.bit.ENPIE = 1;
// PIE中断控制寄存器取回向量使能: ENPIE=PIECRTL[0]
// 当ENPIE=1,所有向量取自PIE向量表,PIE模块使能;
// 当ENPIE=0,PIE模块无效。 (见P185)
// Enable PIE group 2 interrupts 1-8
PieCtrlRegs.PIEIER2.all = 0x00FF;
// PIE中断使能寄存器PIEIERx(x=1-12),高8位保留,低8位为:INTx.8-INTx.1
// 当INTx.y=1,使能中断服务; 当INTx.y=0,将使该位中断服务无效。
// PIEIER2 = 0x00FF,使能 PIE 2组 1-8中断
// Enable CPU INT2
IER |= (M_INT2); // M_INT2=0x0002 (见P57)
// CPU中断使能寄存器: IER[1]=INT2=1,CPU INT2中断使能.
// Make sure PIEACK for group 2 is clear (default after reset)
// 确定PIEACK 2组已清0(复位后的默认值)
PieCtrlRegs.PIEACK.all = M_INT2; // M_INT2=0x0002 (见P185)
// PIE中断应答寄存器 PIEACKx,如果在组中断里有一个中断是未处理的,
// 向各自的中断位写1,使PIE块驱动一个脉冲进入核中断输入。
// PIEACK=M_INT2=0x0002,使PIE块驱动一个脉冲进入INT2核中断输入。
// Force all valid interrupts for Group 2
// 使所有有效中断归入2组
PieCtrlRegs.PIEIFR2.all = ISRS_GROUP2; // ISRS_GROUP2=0x007F (见P187)
// PIE 中断标志寄存器 PIEIFRx(x=1-12),PIE模块(INT1-INT12)
// 使用各个CPU中断中的一个.
// PIEIFRx寄存器高8位保留,低8位依次为: INTx.8-INTx.1,当寄存器位置1,
// 激活对应中断. 当一个中断处理完毕或向该位写0时,该位清0.
// ISRS_GROUP2=(M_INT1|M_INT2|M_INT3|M_INT4|M_INT5|M_INT6|M_INT7)
// 激活2组所有有效中断
// Enable Global interrupts
EINT; //使能全局INTM中断
// Wait for all group 2 interrupts to be serviced
// 等待2组所有中断的中断服务
while(PieCtrlRegs.PIEIFR2.all != 0x0000 ){}
// 当2组所有中断服务完毕,执行下面程序,否则等待
// Stop here and check the order the ISR's were serviced in the
// ISRTrace
// 停止仿真,在ISRTrace缓冲器中检查ISR中断服务程序完成的顺序。
//
asm(" ESTOP0"); // 插入汇编指令: ESTOP0(仿真停止0)
// CASE 3:
// Force all group 3 interrupts at once by writing to the PIEIFR3 register
// 通过写PIEIFR3寄存器激活3组所有有效中断
// Prepare for the test: 准备测试
// Disable interrupts 禁止中断
// Clear the trace buffer, PIE Control Register, CPU IER and IFR registers
// 清跟踪缓冲器,PIE控制寄存器,CPU IER及IFR寄存器。
DINT; //关全局INTM中断
for(i = 0; i < 50; i++) ISRTrace[i] = 0;
ISRTraceIndex = 0;
InitPieCtrl();
IER = 0;
IFR &= 0;
// Enable the PIE block
PieCtrlRegs.PIECRTL.bit.ENPIE = 1;
// PIE中断控制寄存器取回向量使能: ENPIE=PIECRTL[0]
// 当ENPIE=1,所有向量取自PIE向量表,PIE模块使能; 当ENPIE=0,
// PIE模块无效。 (见P185)
// Enable PIE group 3 interrupts 1-8
PieCtrlRegs.PIEIER3.all = 0x00FF;
// PIE中断使能寄存器PIEIERx(x=1-12),高8位保留,
// 低8位为:INTx.8-INTx.1 当INTx.y=1,使能中断服务; 当INTx.y=0,
// 将使该位中断服务无效。PIEIER3 = 0x00FF,使能 PIE 3组 1-8中断
// Make sure PIEACK for group 3 is clear (default after reset)
// 确定PIEACK 3组清0(复位后的默认值)
PieCtrlRegs.PIEACK.all = M_INT3; //(见P185)
// PIE中断应答寄存器 PIEACKx,如果在组中断里有一个中断是未处理的,
// 向各自的中断位写1,使PIE块驱动一个脉冲进入核中断输入。
// PIEACK=M_INT3=0x0004,使PIE块驱动一个脉冲进入INT3核中断输入。
// Enable CPU INT3
IER |= (M_INT3); // M_INT3=0x0004 (见P57)
// CPU中断使能寄存器: IER[2]=INT3=1,CPU INT2中断使能.
// Force all valid interrupts for Group 3
// 使所有有效中断归入3组
PieCtrlRegs.PIEIFR3.all = ISRS_GROUP3; // ISRS_GROUP3=0x007F(见P187)
// PIE 中断标志寄存器 PIEIFRx(x=1-12),PIE模块(INT1-INT12) 使用各个
// CPU中断中的一个.
// PIEIFRx寄存器高8位保留,低8位依次为: INTx.8-INTx.1当寄存器位置1,
// 激活对应中断. 当一个中断处理完毕或向该位写0时,该位清0.
// ISRS_GROUP3=(M_INT1|M_INT2|M_INT3|M_INT4|M_INT5|M_INT6|M_INT7)
// 激活3组所有有效中断
// Enable Global interrupts
EINT; //使能全局中断
// Wait for all group 3 interrupts to be serviced
// 等待3组所有中断闹卸戏?
while(PieCtrlRegs.PIEIFR3.all != 0x0000 ){}
// 当3组所有中断服务完毕,执行下面程序,否则等待
// Stop here and check the order the ISR's were serviced in the
// ISRTrace
// 停止仿真,在ISRTrace缓冲器中检查ISR中断服务程序完成的顺序。
//
asm(" ESTOP0"); // 插入汇编指令: ESTOP0(仿真停止0)
// CASE 4:
// Force all group 4 interrupts at once by writing to the PIEIFR4 register
// 通过写PIEIFR4寄存器激活4组所有有效中断
// Prepare for the test: 准备测试
// Disable interrupts 禁止中断
// Clear the trace buffer, PIE Control Register, CPU IER and IFR registers
// 清跟踪缓冲器,PIE控制寄存器,CPU IER及IFR寄存器。
DINT;
for(i = 0; i < 50; i++) ISRTrace[i] = 0;
ISRTraceIndex = 0;
InitPieCtrl();
IER = 0;
IFR &= 0;
// Enable the PIE block
PieCtrlRegs.PIECRTL.bit.ENPIE = 1; // (见P185)
// PIE中断控制寄存器取回向量使能: ENPIE=PIECRTL[0]
// 当ENPIE=1,所有向量取自PIE向量表,PIE模块使能;
// 当ENPIE=0,PIE模块无效。
// Enable PIE group 4 interrupts 1-8
PieCtrlRegs.PIEIER4.all = 0x00FF;
// PIE中断使能寄存器PIEIERx(x=1-12),高8位保留,
// 低8位为:INTx.8-INTx.1 当INTx.y=1,使能中断服务;
// 当INTx.y=0,将使该位中断服务无效。
// PIEIER4 = 0x00FF,使能 PIE 4组 1-8中断
// Make sure PIEACK for group 3 is clear (default after reset)
// 确定PIEACK 3组已清0(复位后的默认值)
PieCtrlRegs.PIEACK.all = M_INT4; // M_INT4=0x0008 (见P185)
// PIE中断应答寄存器 PIEACKx,如果在组中断里有一个中断是未处理的,
// 向各自的中断位写1,使PIE块驱动一个脉冲进入核中断输入。
// PIEACK=M_INT4=0x0008,使PIE块驱动一个脉冲进入INT4核中断输入。
// Enable CPU INT4 // 使能CPU INT4中断
IER |= (M_INT4); // M_INT4=0x0008 (见P57)
// CPU中断使能寄存器: IER[3]=INT4=1,CPU INT4中断使能.
// Force all valid interrupts for Group 4
// 使所有有效中断归入4组
PieCtrlRegs.PIEIFR4.all = ISRS_GROUP4; // ISRS_GROUP4=0x007F (见P187)
// PIE 中断标志寄存器 PIEIFRx(x=1-12),PIE模块(INT1-INT12)
// 使用各个CPU中断中的一个.
// PIEIFRx寄存器高8位保留,低8位依次为: INTx.8-INTx.1,当寄存器
// 位置1,激活对应中断. 当一个中断处理完毕或向该位写0时,该位清0.
// ISRS_GROUP4=(M_INT1|M_INT2|M_INT3|M_INT4|M_INT5|M_INT6|M_INT7)
// 激活4组所有有效中断
// Enable Global interrupts
EINT; //使能全局INTM中断
// Wait for all group 4 interrupts to be serviced
// 等待4组所有中断的中断服务
while(PieCtrlRegs.PIEIFR4.all != 0x0000 ){}
// 当4组所有中断服务完毕,执行下面程序,否则等待
// Stop here and check the order the ISR's were serviced in the
// 停止仿真,在ISRTrace缓冲器中检查ISR中断服务程序完成的顺序。
//
// ISRTrace
asm(" ESTOP0"); // 插入汇编指令: ESTOP0(仿真停止0)
// CASE 5:
// Force all group 5 interrupts at once by writing to the PIEIFR5 register
// 通过写PIEIFR5寄存器激活5组所有有效中断
// Prepare for the test: 准备测试
// Disable interrupts 禁止中断
// Clear the trace buffer, PIE Control Register, CPU IER and IFR registers
// 清跟踪缓冲器,PIE控制寄存器,CPU IER及IFR寄存器。
DINT;
for(i = 0; i < 50; i++) ISRTrace[i] = 0;
ISRTraceIndex = 0;
InitPieCtrl();
IER = 0;
IFR &= 0;
// Enable the PIE block
PieCtrlRegs.PIECRTL.bit.ENPIE = 1; //(见P185)
// PIE中断控制寄存器取回向量使能: ENPIE=PIECRTL[0]
// 当ENPIE=1,所有向量取自PIE向量表,PIE模块使能.
// 当ENPIE=0,PIE模块无效。
// Enable PIE group 5 interrupts 1-8
PieCtrlRegs.PIEIER5.all = 0x00FF;
// PIE中断使能寄存器PIEIERx(x=1-12),高8位保留,低8位为:INTx.8-INTx.1
// 当INTx.y=1,使能中断服务;
// 当INTx.y=0,将使该位中断服务无效。
// PIEIER5 = 0x00FF,使能 PIE 5组 1-8中断
// Make sure PIEACK for group 5 is clear (default after reset)
PieCtrlRegs.PIEACK.all = M_INT5; // M_INT5=0x0010 (见P185)
// PIE中断应答寄存器 PIEACKx,如果在组中断里有一个中断是未处理的,
// 向各自的中断位写1,使PIE块驱动一个脉冲进入核中断输入。
// PIEACK=M_INT5=0x0010,使PIE块驱动一个脉冲进入INT5核中断输入。
// Enable CPU INT5
IER |= (M_INT5); // M_INT5=0x0010 (见P57)
// CPU中断使能寄存器: IER[4]=INT5=1,CPU INT5中断使能.
// Force all valid interrupts for Group 5
// 使所有有效中断归入5组
PieCtrlRegs.PIEIFR5.all = ISRS_GROUP5; // ISRS_GROUP5=0x007F (见P185)
// PIE 中断标志寄存器 PIEIFRx(x=1-12),PIE模块(INT1-INT12)
// 使用各个CPU中断中的一个.
// PIEIFRx寄存器高8位保留,低8位依次为: INTx.8-INTx.1
// 当寄存器位置1,激活对应中断.
// 当一个中断处理完毕或向该位写0时,该位清0.
// ISRS_GROUP5=(M_INT1|M_INT2|M_INT3|M_INT4|M_INT5|M_INT6|M_INT7)
// 激活5组所有有效中断
// Enable Global interrupts
EINT; //使能全局INTM中断
// Wait for all group 5 interrupts to be serviced
// 等待5组所有中断的中断服务
while(PieCtrlRegs.PIEIFR5.all != 0x0000 ){}
// 当5组所有中断服务完毕,执行下面程序,否则等待
// Stop here and check the order the ISR's were serviced in the
// ISRTrace
// 停止仿真,在ISRTrace缓冲器中检查ISR中断服务程序完成的顺序。
//
asm(" ESTOP0"); // 插入汇编指令: ESTOP0(仿真停止0)
// CASE 6:
// Force all group 6 interrupts at once by writing to the PIEIFR6 register
// 通过写PIEIFR6寄存器激活6组所有有效中断
// Prepare for the test: 准备测试
// Disable interrupts 禁止中断
// Clear the trace buffer, PIE Control Register, CPU IER and IFR registers
// 清跟踪缓冲器,PIE控制寄存器,CPU IER及IFR寄存器。
DINT;
for(i = 0; i < 50; i++) ISRTrace[i] = 0;
ISRTraceIndex = 0;
InitPieCtrl();
IER = 0;
IFR &= 0;
// Enable the PIE block
PieCtrlRegs.PIECRTL.bit.ENPIE = 1; //(见P185)
// PIE中断控制寄存器取回向量使能: ENPIE=PIECRTL[0]
// 当ENPIE=1,所有向量取自PIE向量表,PIE模块使能;
// 当ENPIE=0,PIE模块无效。
// Enable PIE group 6 interrupts 1-8
// 使能PIE模块6组 1-8中断
PieCtrlRegs.PIEIER6.all = 0x00FF;
// PIE中断使能寄存器PIEIERx(x=1-12),高8位保留,低8位为:INTx.8-INTx.1
// 当INTx.y=1,使能中断服务; 当INTx.y=0,将使该位中断服务无效。
// PIEIER6 = 0x00FF,使能 PIE 6组 1-8中断
// Make sure PIEACK for group 6 is clear (default after reset)
// 确定PIEACK 6组已清0(复位后的默认值)
PieCtrlRegs.PIEACK.all = M_INT6; //M_INT6=0x0020 (见P185)
// PIE中断应答寄存器 PIEACKx,如果在组中断里有一个中断是未处理的,
// 向各自的中断位写1,使PIE块驱动一个脉冲进入核中断输入。
// PIEACK=M_INT6=0x0020,使PIE块驱动一个脉冲进入INT6核中断输入。
// Enable CPU INT6
IER |= (M_INT6); // M_INT6=0x0020 (见P57)
// CPU中断使能寄存器: IER[5]=INT6=1,CPU INT6中断使能.
// Force all valid interrupts for Group 6
// 使所有有效中断归入6组
PieCtrlRegs.PIEIFR6.all = ISRS_GROUP6; // ISRS_GROUP6=0x0033 (见P187)
// PIE 中断标志寄存器 PIEIFRx(x=1-12),PIE模块(INT1-INT12)
// 使用各个CPU中断中的一个.
// PIEIFRx寄存器高8位保留,低8位依次为: INTx.8-INTx.1
// 当寄存器位置1,激活对应中断;
// 当一个中断处理完毕或向该位写0时,该位清0.
// ISRS_GROUP6=(M_INT1|M_INT2|M_INT5|M_INT6)
// 激活6组所有有效中断
// Enable Global interrupts
EINT; //使能全局INTM中断
// Wait for all group 6 interrupts to be serviced
// 等待6组所有中断的中断服务
while(PieCtrlRegs.PIEIFR6.all != 0x0000 ){}
// 当6组所有中断服务完毕,执行下面程序,否则等待
// Stop here and check the order the ISR's were serviced in the
// ISRTrace
// 停止仿真,在ISRTrace缓冲器中检查ISR中断服务程序完成的顺序。
//
asm(" ESTOP0"); // 插入汇编指令: ESTOP0(仿真停止0)
// CASE 8:
// Force all group 9 interrupts at once by writing to the PIEIFR4 register
// 通过写PIEIFR4寄存器激活9组所有有效中断
// Prepare for the test: 准备测试
// Disable interrupts 禁止中断
// Clear the trace buffer, PIE Control Register, CPU IER and IFR registers
// 清跟踪缓冲器,PIE控制寄存器,CPU IER及IFR寄存器。
DINT;
for(i = 0; i < 50; i++) ISRTrace[i] = 0;
ISRTraceIndex = 0;
InitPieCtrl();
IER = 0;
IFR &= 0;
// Enable the PIE block
PieCtrlRegs.PIECRTL.bit.ENPIE = 1; //(见P185)
// PIE中断控制寄存器取回向量使能: ENPIE=PIECRTL[0]
// 当ENPIE=1,所有向量取自PIE向量表,PIE模块使能;
// 当ENPIE=0,PIE模块无效。
// Enable PIE group 9 interrupts 1-8
PieCtrlRegs.PIEIER9.all = 0x00FF; //(见P186)
// PIE中断使能寄存器PIEIERx(x=1-12),高8位保留,低8位为:INTx.8-INTx.1
// 当INTx.y=1,使能中断服务; 当INTx.y=0,将使该位中断服务无效。
// PIEIER9 = 0x00FF,使能 PIE 9组 1-8中断
// Make sure PIEACK for group 9 is clear (default after reset)
PieCtrlRegs.PIEACK.all = M_INT9; // M_INT9=0x0100 (见P185)
// PIE中断应答寄存器 PIEACKx,如果在组中断里有一个中断是未处理的,
// 向各自的中断位写1,使PIE块驱动一个脉冲进入核中断输入。
// PIEACK=M_INT9=0x0002,使PIE块驱动一个脉冲进入INT9核中断输入。
// Enable CPU INT9
IER |= (M_INT9); // M_INT9=0x0100 (见P57)
// CPU中断使能寄存器: IER[8]=INT9=1,CPU INT9中断使能.
// Force all valid interrupts for Group 9
// 使所有有效中断归入9组
PieCtrlRegs.PIEIFR9.all = ISRS_GROUP9; // ISRS_GROUP9=0x001F (见P185)
// PIE 中断标志寄存器 PIEIFRx(x=1-12),PIE模块(INT1-INT12)
// 使用各个CPU中断中的一个.
// PIEIFRx寄存器高8位保留,低8位依次为: INTx.8-INTx.1
// 当寄存器位置1,激活对应中断;
// 当一个中断处理完毕或向该位写0时,该位清0.
// ISRS_GROUP9=(M_INT1|M_INT2|M_INT3|M_INT4|M_INT5)
// 激活 9组所有有效中断
// Enable Global interrupts
EINT; //使能全局INTM中断
// Wait for all group 9 interrupts to be serviced
// 等待9组所有中断的中断服务
while(PieCtrlRegs.PIEIFR9.all != 0x0000 ){}
// 当2组所有中断服务完毕,执行下面程序,否则等待
// Stop here and check the order the ISR's were serviced in the
// ISRTrace
// 停止仿真,在ISRTrace缓冲器中检查ISR中断服务程序完成的顺序。
//
asm(" ESTOP0"); // 插入汇编指令: ESTOP0(仿真停止0)
// CASE 9:
// Force all group 1 and group 2 interrupts at once // 激活1,2组所有有效中断
// Setup next test - fire interrupts from Group 1 and Group 2
// 设置来自1组和2组的下一个中断测试
// Prepare for the test: 准备测试
// Disable interrupts 禁止中断
// Clear the trace buffer, PIE Control Register, CPU IER and IFR registers
// 清跟踪缓冲器,PIE控制寄存器,CPU IER及IFR寄存器。
DINT;
for(i = 0; i < 50; i++) ISRTrace[i] = 0;
ISRTraceIndex = 0;
InitPieCtrl();
IER = 0;
IFR &= 0;
// Enable the PIE block
PieCtrlRegs.PIECRTL.bit.ENPIE = 1; //(见P185)
// PIE中断控制寄存器取回向量使能: ENPIE=PIECRTL[0]
// 当ENPIE=1,所有向量取自PIE向量表,PIE模块使能; 当ENPIE=0,
// PIE模块无效。
// Enable PIE group 1 and group 2 interrupts 1-8
PieCtrlRegs.PIEIER1.all = 0x00FF; //(见P186)
PieCtrlRegs.PIEIER2.all = 0x00FF;
// PIE中断使能寄存器PIEIERx(x=1-12),高8位保留,低8位为:INTx.8-INTx.1
// 当INTx.y=1,使能中断服务; 当INTx.y=0,将使该位中断服务无效。
// PIEIER1 = 0x00FF,使能 PIE 1组 1-8中断
// PIEIER2 = 0x00FF,使能 PIE 2组 1-8中断
// Make sure PIEACK for group 1 & 2 are clear (default after reset)
// 确定PIEACK 1组和3组已清0(复位后的默认值)
PieCtrlRegs.PIEACK.all = (M_INT3 | M_INT2); //(见P185)
// M_INT3=0x0004 M_INT2=0x0002
// PIE中断应答寄存器 PIEACKx,如果在组中断里有一个中断是未处理的,
// 向各自的中断位写1,使PIE块驱动一个脉冲进入核中断输入。
// PIEACK=(M_INT3 | M_INT2)=0x0006,
// 使PIE块驱动2个脉冲进入INT3及INT2核中断输入。
// Enable CPU INT1 and INT2
IER |= (M_INT1|M_INT2); // (M_INT3 | M_INT2)=0x0006 (见P57)
// CPU中断使能寄存器: IER[2]=INT3=1,IER[1]=INT2=1
// CPU INT3,INT2中断使能.
// Force all valid interrupts for Group 1 and from Group 2
// 使所有有效中断归入1组及2组
PieCtrlRegs.PIEIFR1.all = ISRS_GROUP1; // ISRS_GROUP1=0x00FB (见P187)
PieCtrlRegs.PIEIFR2.all = ISRS_GROUP2; // ISRS_GROUP2=0x007F
// PIE 中断标志寄存器 PIEIFRx(x=1-12),PIE模块(INT1-INT12)
// 使用各个CPU中断中的一个.
// PIEIFRx寄存器高8位保留,低8位依次为: INTx.8-INTx.1,
// 当寄存器位置1,激活对应中断;
// 当一个中断处理完毕或向该位写0时,该位清0.
// ISRS_GROUP1=(M_INT1|M_INT2|M_INT4|M_INT5|M_INT6|M_INT7|M_INT8)
// ISRS_GROUP2=(M_INT1|M_INT2|M_INT3|M_INT4|M_INT5|M_INT6|M_INT7)
// 激活1,2组所有有效中断
// Enable Global interrupts
EINT; //使能全局INTM中断
// Wait for all group 1 and group 2 interrupts to be serviced
// 等待4组所有中断的中断服务
while(PieCtrlRegs.PIEIFR1.all != 0x0000
|| PieCtrlRegs.PIEIFR2.all != 0x0000 ){}
// 当1组和2组所有中断服务完毕,执行下面程序,否则等待
// Check the ISRTrace to determine which order the
// ISR Routines completed
// 停止仿真,检查ISRTrace缓冲器,以便测定ISR中断服务程序完成的顺序。
asm(" ESTOP0"); // 插入汇编指令: ESTOP0(仿真停止0)
// CASE 10:
// Force all group 1 and group 2 and group 3 interrupts at once // 激活1,2及3组所有中断
// Prepare for the test: 准备测试
// Disable interrupts 禁止中断
// Clear the trace buffer, PIE Control Register, CPU IER and IFR registers // 清跟踪缓冲器,PIE控制寄存器,CPU IER及IFR寄存器。
DINT;
for(i = 0; i < 50; i++) ISRTrace[i] = 0;
ISRTraceIndex = 0;
InitPieCtrl();
IER = 0;
IFR &= 0;
// Enable the PIE block
PieCtrlRegs.PIECRTL.bit.ENPIE = 1; //(见P185)
// PIE中断控制寄存器取回向量使能: ENPIE=PIECRTL[0]
// 当ENPIE=1,所有向量取自PIE向量表,PIE模块使能;
// 当ENPIE=0,IE模块无效。
PieCtrlRegs.PIEIER1.all = 0x00FF;
PieCtrlRegs.PIEIER2.all = 0x00FF;
PieCtrlRegs.PIEIER3.all = 0x00FF;
// Enable PIE group 1, 2 and 3 interrupts 1-8
// PIE中断使能寄存器PIEIERx(x=1-12),高8位保留,低8位为:INTx.8-INTx.1
// 当INTx.y=1,使能中断服务; 当INTx.y=0,将使该位中断服务无效。
// PIEIER1 = 0x00FF,使能 PIE 1组 1-8中断
// PIEIER2 = 0x00FF,使能 PIE 2组 1-8中断
// PIEIER3 = 0x00FF,使能 PIE 3组 1-8中断
// Make sure PIEACK for group 1, 2 & 3 are clear (default after reset)
// 确定PIEACK 1,2,3组已清0(复位后的默认值)
PieCtrlRegs.PIEACK.all = (M_INT1|M_INT2|M_INT3);
// M_INT1=0x0001 M_INT2=0x0002 M_INT3=0x0004
// PIE中断应答寄存器 PIEACKx,如果在组中断里有一个中断是未处理的,
// 向各自的中断位写1,使PIE块驱动一个脉冲进入核中断输入。
// PIEACK=(M_INT1|M_INT2|M_INT3)=0x0007,
// 使PIE块驱动3个脉冲进入INT1,INT2及INT3核中断输入。
// Enable CPU INT1, INT2 & INT3
IER |= (M_INT1|M_INT2|M_INT3); //(见P57)
// CPU中断使能寄存器: IER[0]=INT1=1,IER[1]=INT2=1,IER[2]=INT3=1
// CPU INT1,INT2及INT3中断使能.
// Force all valid interrupts for Group1, 2 and 3
// 使能1,2及3组所有有效中断
PieCtrlRegs.PIEIFR1.all = ISRS_GROUP1; // ISRS_GROUP1=0x00FB (见P185)
PieCtrlRegs.PIEIFR2.all = ISRS_GROUP2; // ISRS_GROUP2=0x007F
PieCtrlRegs.PIEIFR3.all = ISRS_GROUP3; // ISRS_GROUP3=0x007F
// PIE 中断标志寄存器 PIEIFRx(x=1-12),PIE模块(INT1-INT12)
// 使用各个CPU中断中的一个.
// PIEIFRx寄存器高8位保留,低8位依次为: INTx.8-INTx.1,
// 当寄存器位置1,激活对应中断;
// 当一个中断处理完毕或向该位写0时,该位清0.
// ISRS_GROUP1=(M_INT1|M_INT2|M_INT4|M_INT5|M_INT6|M_INT7|M_INT8)
// ISRS_GROUP2=(M_INT1|M_INT2|M_INT3|M_INT4|M_INT5|M_INT6|M_INT7)
// ISRS_GROUP3=(M_INT1|M_INT2|M_INT3|M_INT4|M_INT5|M_INT6|M_INT7)
// 使能1,2及3组所有有效中断
// Enable Global interrupts
EINT; //使能全局INTM中断
// Wait for all group 1 and group 2 and group 3
// interrupts to be serviced
// 等待1,2及3组所有中断的中断服务
while(PieCtrlRegs.PIEIFR1.all != 0x0000
|| PieCtrlRegs.PIEIFR2.all != 0x0000
|| PieCtrlRegs.PIEIFR3.all != 0x0000 ) {}
// 当1,2及3组所有中断服务完毕,执行下面程序,否则等待
// Check the ISRTrace to determine which order the
// ISR Routines completed
// 停止仿真,检查ISRTrace缓冲器,以便测定ISR中断服务程序完成的顺序。
asm(" ESTOP0"); // 插入汇编指令: ESTOP0(仿真停止0)
// CASE 11:
// Force all used PIE interrupts at once // 使能上面曾用到的所有PIE中断
// Prepare for the test: 准备测试
// Disable interrupts 禁止中断
// Clear the trace buffer, PIE Control Register, CPU IER and IFR registers
// 清跟踪缓冲器,PIE控制寄存器,CPU IER及IFR寄存器。
DINT;
for(i = 0; i < 50; i++) ISRTrace[i] = 0;
ISRTraceIndex = 0;
InitPieCtrl();
IER = 0;
IFR &= 0;
// Enable the PIE block
PieCtrlRegs.PIECRTL.bit.ENPIE = 1; //(见P185)
// PIE中断控制寄存器取回向量使能: ENPIE=PIECRTL[0]
// 当ENPIE=1,所有向量取自PIE向量表,PIE模块使能;
// 当ENPIE=0,PIE模块无效。
// Enable all PIE group iterrupts 1-8
// 使能 PIE 全组 1-8中断
PieCtrlRegs.PIEIER1.all = 0x00FF; //(见P186)
PieCtrlRegs.PIEIER2.all = 0x00FF;
PieCtrlRegs.PIEIER3.all = 0x00FF;
PieCtrlRegs.PIEIER4.all = 0x00FF;
PieCtrlRegs.PIEIER5.all = 0x00FF;
PieCtrlRegs.PIEIER6.all = 0x00FF;
PieCtrlRegs.PIEIER9.all = 0x00FF;
// PIE中断使能寄存器PIEIERx(x=1-12),高8位保留,低8位为:INTx.8-INTx.1
// 当INTx.y=1,使能中断服务; 当INTx.y=0,将使该位中断服务无效。
// PIEIER1 = 0x00FF,使能 PIE 1组 1-8中断
// PIEIER2 = 0x00FF,使能 PIE 2组 1-8中断
// PIEIER3 = 0x00FF,使能 PIE 3组 1-8中断
// PIEIER4 = 0x00FF,使能 PIE 4组 1-8中断
// PIEIER5 = 0x00FF,使能 PIE 5组 1-8中断
// PIEIER6 = 0x00FF,使能 PIE 6组 1-8中断
// PIEIER9 = 0x00FF,使能 PIE 9组 1-8中断
// Make sure PIEACK for group 1, 2, 3, 4, 5, 6 and 9 are clear
// (default after reset)
// 确定PIEACK 1,2,3,4,5,6及9组已清0(复位后的默认值)
PieCtrlRegs.PIEACK.all =
(M_INT1|M_INT2|M_INT3|M_INT4|M_INT5|M_INT6|M_INT9);
// M_INT1=0x0001 M_INT2=0x0002 M_INT3=0x0004 M_INT4=0x0008
// M_INT5=0x0010 M_INT6=0x0020 M_INT9=0x0100 (见P185)
// PIE中断应答寄存器 PIEACKx,如果在组中断里有一个中断是未处理的,
// 向各自的中断位写1,使PIE块驱动一个脉冲进入核中断输入。
// PIEACK=M_INT4=0x012F,使PIE块驱动7个脉冲进入INT1,INT2,INT3,
// INT4,INT5,INT6及INT9核中断输入。
// Enable CPU INT1, INT2, INT3, INT4, INT5, INT6 and INT9
IER |= (M_INT1|M_INT2|M_INT3|M_INT4|M_INT5|M_INT6|M_INT9); //(见P57)
// CPU中断使能寄存器:
// IER[]=(M_INT1|M_INT2|M_INT3|M_INT4|M_INT5|M_INT6|M_INT9)=0x012F,
// CPU INT1,INT2,INT3,INT4,INT5,INT6及INT9中断使能.
// Force all valid interrupts for all PIE groups
// 使能PIE 全组 所有有效中断
PieCtrlRegs.PIEIFR1.all = ISRS_GROUP1; // ISRS_GROUP1=0x00FB //(见P187)
PieCtrlRegs.PIEIFR2.all = ISRS_GROUP2; // ISRS_GROUP2=0x007F
PieCtrlRegs.PIEIFR3.all = ISRS_GROUP3; // ISRS_GROUP3=0x007F
PieCtrlRegs.PIEIFR4.all = ISRS_GROUP4; // ISRS_GROUP4=0x007F
PieCtrlRegs.PIEIFR5.all = ISRS_GROUP5; // ISRS_GROUP5=0x007F
PieCtrlRegs.PIEIFR6.all = ISRS_GROUP6; // ISRS_GROUP6=0x0033
PieCtrlRegs.PIEIFR9.all = ISRS_GROUP9; // ISRS_GROUP9=0x001F
// PIE 中断标志寄存器 PIEIFRx(x=1-12),PIE模块(INT1-INT12)
// 使用各个CPU中断中的一个.
// PIEIFRx寄存器高8位保留,低8位依次为: INTx.8-INTx.1,
// 当寄存器位置1,激活对应中断;
// 当一个中断处理完毕或向该位写0时,该位清0.
// ISRS_GROUP1=(M_INT1|M_INT2|M_INT4|M_INT5|M_INT6|M_INT7|M_INT8)
// ISRS_GROUP2=(M_INT1|M_INT2|M_INT3|M_INT4|M_INT5|M_INT6|M_INT7)
// ISRS_GROUP3=(M_INT1|M_INT2|M_INT3|M_INT4|M_INT5|M_INT6|M_INT7)
// ISRS_GROUP4=(M_INT1|M_INT2|M_INT3|M_INT4|M_INT5|M_INT6|M_INT7)
// ISRS_GROUP5=(M_INT1|M_INT2|M_INT3|M_INT4|M_INT5|M_INT6|M_INT7)
// ISRS_GROUP6=(M_INT1|M_INT2|M_INT5|M_INT6)
// ISRS_GROUP9=(M_INT1|M_INT2|M_INT3|M_INT4|M_INT5)
// 使能上列1,2,3,4,5,6及9组所有中断
// Enable Global interrupts - CPU level
EINT; //使能全局INTM中断
// Wait for all group interrupts to be serviced
// 等待全组所有中断的中断服务
while(PieCtrlRegs.PIEIFR1.all != 0x0000 //(见P186)
|| PieCtrlRegs.PIEIFR2.all != 0x0000
|| PieCtrlRegs.PIEIFR3.all != 0x0000
|| PieCtrlRegs.PIEIFR4.all != 0x0000
|| PieCtrlRegs.PIEIFR5.all != 0x0000
|| PieCtrlRegs.PIEIFR6.all != 0x0000
|| PieCtrlRegs.PIEIFR9.all != 0x0000 ) {}
// 当全组所有中断服务完毕,执行下面程序,否则等待
// Check the ISRTrace to determine which order the
// ISR Routines completed
// 停止仿真,检查ISRTrace缓冲器,以便测定ISR中断服务程序完成的顺序。
asm(" ESTOP0"); // 插入汇编指令: ESTOP0(仿真停止0)
}
//=========================================================================== // No more.
//===========================================================================
实验9 外部扩展接口运行实验
文 件: Example_281xCodeRunFromXintf.c 标 题: 从外部扩展接口运行示例程序。
条 件: 本程序需要DSP281x V1.00头文件支持,另外取出JP2跳线,即置MP/MC=1(微控制器方
式,XINTF 7区使能),将程序引导到从外部扩展接口7区(XINTF Zone 7)运行。将外部扩展接口
7区映射到CC内部的RAM区域。查阅CCS提供的F2812.gel文件。 说 明: 本示例配置成CPU定时器0方式,并且对定时器的每一次中断计数器取增量。 /观察变量: CpuTimer0.InterruptCount CPU定时器0中断计数器
BackGroundCounter 归0计数器
*****************************************************************************************/
// 步骤0: 包含所需的头文件。
// DSP281x_Device.h头文件包含器件的特殊定义以及用#include声明的所有外设 .h定义文件 #include "DSP281x_Device.h" // DSP281x 头文件包含文件
#include "DSP281x_Examples.h" // DSP281x 示例包含文件
// 由本文件建立的函数原型声明。把这个函数分配到连接内部RAM的一个区域。 #pragma CODE_SECTION(xintf_zone6and7_timing,"ramfuncs");
void xintf_zone6and7_timing(void); interrupt void ISR_CPUTimer0(void); void error(void);
// 在本文件内建立的全局变量。
Uint32 BackgroundCount = 0;
// RAM计数器-该计数器存放在RAM内,与存放在XINTF中的进行比较。 #pragma DATA_SECTION(RamInterruptCount,"ramdata"); Uint32 RamInterruptCount = 0;
void LedD_Display(void);
void LedH_Display(void);
Uint16 count=0;
void main(void)
{
//-----------------------------------------------------------------------
// 所有的设计(程序)都必须遵循步骤1到步骤5的步骤。
// 步骤1: 关闭和清除CPU所有中断:
DINT;
IER = 0x0000;
IFR = 0x0000;
// 步骤2: 初始化系统控制寄存器,锁相环,看门狗,时钟为默认状态:
InitSysCtrl(); // 该函数由DSP281x_SysCtrl.c文件建立
// 步骤3. 根据设计或者特殊应用选择GPIO。这个函数由DSP281x_Gpio.c文件建立
//InitGpio(); // 本例不需要
// 步骤4. 初始化PIE为已知状态(控制寄存器及向量表):
// 初始化PIE向量表,该向量表指明了中断服务程序(ISR)的一种构架(壳)。
// 这个壳程序通过DSP281x_DefaultIsr.c文件建立.在DSP281x_DefaultIsr.c文件
// 内适当的壳ISR程序中可以嵌入用户的特殊的ISR代码.
// 初始化PIE控制寄存器为默认状态。这个函数通过DSP281x_PieCtrl.c文件建立。
InitPieCtrl();
// 初始化PIE向量表为已知状态。这个函数通过DSP281x_PieVect.c.文件建立。
// 这个函数用来板上组装PIE向量表,这张表由DSP281x_DefaultIsr.c文件建立,
// 它指出了中断服务程序(ISR)的一种构架(壳)。
InitPieVectTable();
// 使能CPU及PIE中断。这个示例函数由DSP281x_PieCtrl.c文件建立。
EnableInterrupts();
// 步骤5. 初始化器件所有外设为已知状态。
// 这个函数由DSP281x_InitPeripherals.c文件建立。
//InitPeripherals(); // 本例仅初始化CPU定时器
InitCpuTimers();
//-----------------------------------------------------------------------
// 用户绝对代码:
// 初始化 XINTF Zone 6区及 Zone 7区定时.首先将函数拷贝到RAM,然后调用
// 函数改变 zone 区定时.
// RamfuncsLoadStart, RamfuncsLoadEnd 及 RamfuncsRunStart 符号由连接器
// 生成. 查阅CodeRunFromXintfonF2812EzDSP.cmd文件
MemCopy(&RamfuncsLoadStart, &RamfuncsLoadEnd, &RamfuncsRunStart);
xintf_zone6and7_timing();
EALLOW; // 允许访问受保护的寄存器
PieVectTable.TINT0 = &ISR_CPUTimer0;
EDIS; // 禁止访问受保护的寄存器
PieCtrlRegs.PIEIER1.bit.INTx7 = 1; // 使能PIE 1组第7个(INT1.7)
// 即TINT0(CPU-定时器0)中断
IER |= M_INT1;
// 在DSP281x_Device.h文件中,已经定义 M_INT1=0x0001, P57
// IER为CPU中断使能寄存器,这条指令de含义为: 使能CPU INT1第一组中断。
// 这里用了按位或复合运算符"|=",其用意是不破坏IER原有结构。不能简单
// 地用 "IER = 0x0001;" 指令。如此,IER原有结构被破坏了。
SetDBGIER(M_INT1); // 使能INT1实时模式
EINT; // 使能INTM全局中断
ERTM; // 使能DBGM全局实时中断
// 配置和初始化CPU定时器0:CPU定时器0连接到INT1.7; 设置1秒中断周期; 指向
// "ISR_CPUTimer0"函数.
ConfigCpuTimer(&CpuTimer0, 150, 1000000); // 150MHz CPU频率,1秒周期(in uSeconds)
StartCpuTimer0();
for(;;) // 下面程序段无限循环
{
BackgroundCount++;
count=BackgroundCount;
LedD_Display();
LedH_Display();
}
exit(0); // 运行程序决不会到达此处.
}
/******************************************************************************************
函数: ISR_CPUTimer0()
功能: CPU定时器0中断服务程序
******************************************************************************************/
interrupt void ISR_CPUTimer0(void)
{
PieCtrlRegs.PIEACK.all = 0xFFFF;
ERTM; // 使能DBGM全局实时中断.
CpuTimer0.InterruptCount++; // 每过1秒取增量.
RamInterruptCount++;
if(RamInterruptCount != CpuTimer0.InterruptCount) error();
}
/******************************************************************************************
函 数: xintf_zone6and7_timing()
功 能: 对Zone 6区及Zone 7区配置定时参数
注 意: 在这种配置下,该函数不能够在同一区中执行。
******************************************************************************************/
void xintf_zone6and7_timing()
{
//#################### 所有 Zones 区 ######################// P110
XintfRegs.XINTCNF2.bit.XTIMCLK = 0;
// XINTCNF2[18:16]=WRBUFF=000 b, 所有zones区定时基于XTIMCLK = SYSCLKOUT
XintfRegs.XINTCNF2.bit.WRBUFF = 3;
// XINTCNF2[1:0]=WRBUFF=11 b, 当前写缓冲器为3个值
XintfRegs.XINTCNF2.bit.CLKOFF = 0;
// XINTCNF2[3]=CLKOFF=0, 使能XCLKOUT
XintfRegs.XINTCNF2.bit.CLKMODE = 0;
// XINTCNF2[2]=CLKMODE=0, XCLKOUT = XTIMCLK
//######################## Zone 6 ##########################//
// 当准备时,激活必须为1个或更多XTIMCLK 个周期。
// 引导必须总为1个或更多XTIMCLK 个周期。
// Zone 6 区写定时 P106-P109
XintfRegs.XTIMING6.bit.XWRLEAD = 1;
// XTIMING6[6:5]=XWRLEAD=01 b,由X2TIMING=0,缩放比例为1:1(不加倍),
// 故写引导周期为 1* XTIMCLK 个周期。
XintfRegs.XTIMING6.bit.XWRACTIVE = 1;
// XTIMING6[4:2]=XWRACTIVE=001 b,由X2TIMING=0,缩放比例为1:1(不加倍),
// 故写激活时间等待状态为1* XTIMCLK 个周期。
XintfRegs.XTIMING6.bit.XWRTRAIL = 1;
// XTIMING6[1:0]=XWRTRAIL=01 b,由X2TIMING=0,缩放比例为1:1(不加倍),
// 故写跟踪周期为1* XTIMCLK 个周期。
// Zone 6 区读定时
XintfRegs.XTIMING6.bit.XRDLEAD = 1;
// XTIMING6[13:12]=XRDLEAD=01 b,由X2TIMING=0,缩放比例为1:1(不加倍),
// 故读引导周期为1* XTIMCLK 个周期。
XintfRegs.XTIMING6.bit.XRDACTIVE = 2;
// XTIMING6[11:9]=XRDACTIVE=010 b,由X2TIMING=0,缩放比例为1:1(不加倍),
// 故读激活时间等待状态为2* XTIMCLK 个周期。
XintfRegs.XTIMING6.bit.XRDTRAIL = 0;
// XTIMING6[8:7]=XRDTRAIL=00 b,由X2TIMING=0,缩放比例为1:1(不加倍),
// 故读跟踪周期为1* XTIMCLK 个周期。
XintfRegs.XTIMING6.bit.X2TIMING = 0; // 所有Zone区读/写 引导/激活/跟踪定时不加倍。
XintfRegs.XTIMING6.bit.USEREADY = 0;
// XTIMING6[14]=USEREADY=0,区访问时,忽略XREADY引脚信号。
XintfRegs.XTIMING6.bit.READYMODE = 0;
// XTIMING6[15]=READYMODE=0,XREADY引脚输入为同步方式
XintfRegs.XTIMING6.bit.XSIZE = 3;
// XTIMING6[17:16]=XSIZE=11 b,16位接口。XSIZE=11 b 是唯一正确的组合。
// 其它组合将导致不正确的XINTF行为。
//######################## Zone 7 ##########################//
// 当准备时,激活必须为1个或更多XTIMCLK 个周期。
// 引导必须总为1个或更多XTIMCLK 个周期。
// Zone 7 区写定时 P106-P109
XintfRegs.XTIMING7.bit.XWRLEAD = 1;
// XTIMING6[6:5]=XWRLEAD=01 b,由X2TIMING=0,缩放比例为1:1(不加倍),
// 故写引导周期为 1* XTIMCLK 个周期。
XintfRegs.XTIMING7.bit.XWRACTIVE = 1;
// XTIMING6[4:2]=XWRACTIVE=001 b,由X2TIMING=0,缩放比例为1:1(不加倍),
// 故写激活时间等待状态为1* XTIMCLK 个周期。
XintfRegs.XTIMING7.bit.XWRTRAIL = 1;
// XTIMING6[1:0]=XWRTRAIL=01 b,由X2TIMING=0,缩放比例为1:1(不加倍),
// 故写跟踪周期为1* XTIMCLK 个周期。
// Zone 7 区读定时
XintfRegs.XTIMING7.bit.XRDLEAD = 1;
// XTIMING6[13:12]=XRDLEAD=01 b,由X2TIMING=0,缩放比例为1:1(不加倍),
// 故读引导周期为1* XTIMCLK 个周期。
XintfRegs.XTIMING7.bit.XRDACTIVE = 2;
// XTIMING6[11:9]=XRDACTIVE=010 b,由X2TIMING=0,缩放比例为1:1(不加倍),
// 故读激活时间等待状态为2* XTIMCLK 个周期。
XintfRegs.XTIMING7.bit.XRDTRAIL = 0;
// XTIMING6[8:7]=XRDTRAIL=00 b,由X2TIMING=0,缩放比例为1:1(不加倍),
// 故读跟踪周期为1* XTIMCLK 个周期。
XintfRegs.XTIMING7.bit.X2TIMING = 0; // 所有Zone区读/写 引导/激活/跟踪定时不加倍。
XintfRegs.XTIMING7.bit.USEREADY = 0;
// XTIMING6[14]=USEREADY=0,区访问时,忽略XREADY引脚信号。
XintfRegs.XTIMING7.bit.READYMODE = 0;
// XTIMING6[15]=READYMODE=0,XREADY引脚输入为同步方式
XintfRegs.XTIMING7.bit.XSIZE = 3;
// XTIMING6[17:16]=XSIZE=11 b,16位接口。XSIZE=11 b 是唯一正确的组合。
// 其它组合将导致不正确的XINTF行为。
// 强制一个流水线开通以便确保在返回之前写完最后寄存器配置.
asm(" RPT #7 || NOP");
}
/****************************************************************************************** 函数: error()
功能: 出错处理
******************************************************************************************/ void error(void)
{
asm(" ESTOP0"); // 软件断点
}
//================================================================================ // No more.
//================================================================================
实验10 DAC实验
文 件: DACtest.c
标 题: DSP281x Device DAC test porgram.
********************************************************************************************
#include "DSP281x_Device.h" // DSP281x Headerfile Include File #include "DSP281x_Examples.h" // DSP281x Examples Include File
// CPU I/O端口定义
#define Tlv_Out GpioMuxRegs.GPGDIR.bit.GPIOG5=1
// 定义 Tlv_Out: GPIOG5为输出
#define Tlv_High GpioDataRegs.GPGSET.bit.GPIOG5=1
// 定义 Tlv_High: 置GPIOG5为高电平
#define Tlv_Low GpioDataRegs.GPGCLEAR.bit.GPIOG5=1
// 定义 Tlv_Low: 置GPIOG5为低电平
// Prototype statements for functions found within this file.
// interrupt void ISRTimer2(void);
interrupt void spiTxFifoIsr(void);
interrupt void spiRxFifoIsr(void);
void delay_loop(void);
void spi_fifo_init(void);
void error();
void delay();
Uint16 sdata[8]; // Send data buffer
Uint16 rdata[8]; // Receive data buffer
Uint16 rdata_point; // Keep track of where we are in the data stream to check received data
Uint16 temp=0;
void main(void)
{
Uint16 i;
// Step 1. Initialize System Control:
// PLL, WatchDog, enable Peripheral Clocks
// This example function is found in the DSP281x_SysCtrl.c file.
InitSysCtrl();
// Step 2. Initalize GPIO:
// This example function is found in the DSP281x_Gpio.c file and
// illustrates how to set the GPIO to it's default state. // InitGpio(); // Skipped for this example
// Setup only the GP I/O only for SPI functionality
EALLOW;
GpioMuxRegs.GPFMUX.all=0x000F; // Select GPIOs to be SPI pins
// Port F MUX - x000 0000 0000 1111
EDIS;
EALLOW;
GpioMuxRegs.GPGDIR.bit.GPIOG5=1;
EDIS;
// Step 3. Initialize PIE vector table:
// Disable and clear all CPU interrupts
DINT;
IER = 0x0000;
IFR = 0x0000;
// Initialize PIE control registers to their default state:
// This function is found in the DSP281x_PieCtrl.c file.
InitPieCtrl();
// Initialize the PIE vector table with pointers to the shell Interrupt Service Routines (ISR).
// This will populate the entire table, even if the interruptis not used in this example.
// This is useful for debug purposes.
// The shell ISR routines are found in DSP281x_DefaultIsr.c.
// This function is found in DSP281x_PieVect.c.
InitPieVectTable();
// Interrupts that are used in this example are re-mapped to
// ISR functions found within this file.
EALLOW; // This is needed to write to EALLOW protected registers
PieVectTable.SPIRXINTA = &spiRxFifoIsr;
PieVectTable.SPITXINTA = &spiTxFifoIsr;
EDIS; // This is needed to disable write to EALLOW protected registers
//Init SCITXA,RXA as io ports
EALLOW;
GpioMuxRegs.GPFMUX.bit.SCITXDA_GPIOF4 =0;
GpioMuxRegs.GPFMUX.bit.SCIRXDA_GPIOF5 =0;
GpioMuxRegs.GPFDIR.bit.GPIOF4 =1;
GpioMuxRegs.GPFDIR.bit.GPIOF5 =1; // upper byte as output/low byte as input
GpioMuxRegs.GPAQUAL.all=0x0000; // Input qualifier disabled
EDIS;
// Step 4. Initialize all the Device Peripherals:
// This function is found in DSP281x_InitPeripherals.c // InitPeripherals(); // Not required for this example
spi_fifo_init(); // Initialize the SPI only
// Step 5. User specific code, enable interrupts:
// Initalize the send data buffer
for(i=0; i<8; i++)
{
sdata[i] = i;
}
rdata_point = 0;
GpioDataRegs.GPFDAT.bit.GPIOF4=1;
GpioDataRegs.GPFDAT.bit.GPIOF5 =0;
// Enable interrupts required for this example
PieCtrlRegs.PIECRTL.bit.ENPIE = 1; // Enable the PIE block
// PieCtrlRegs.PIEIER6.bit.INTx1=1; // Enable PIE Group 6, INT 1
PieCtrlRegs.PIEIER6.bit.INTx2=1; // Enable PIE Group 6, INT 2
IER=0x20; // Enable CPU INT6
EINT; // Enable Global Interrupts
// Step 6. IDLE loop. Just sit and loop forever (optional): for(;;);
}
// Some Useful local functions
void delay_loop()
{
long i;
for (i = 0; i < 1000000; i++) {}
}
void error(void)
{
asm(" ESTOP0"); //Test failed!! Stop!
for (;;);
}
void spi_fifo_init()
{
// Initialize SPI FIFO registers for DA
SpiaRegs.SPICCR.bit.SPISWRESET=0; // Reset SPI
SpiaRegs.SPICCR.all=0x000F; //16-bit character, no Loopback mode
SpiaRegs.SPICTL.all=0x0017; //Interrupt enabled, Master/Slave XMIT enabled
SpiaRegs.SPISTS.all=0x0000;
SpiaRegs.SPIBRR=0x0063; // Baud rate
SpiaRegs.SPIFFTX.all=0xC028; // Enable FIFO's, set TX FIFO level to 8
SpiaRegs.SPIFFRX.all=0x0028; // Set RX FIFO level to 31
SpiaRegs.SPIFFCT.all=0x00;
SpiaRegs.SPIPRI.all=0x0010;
SpiaRegs.SPICCR.bit.SPISWRESET=1; // Enable SPI
SpiaRegs.SPIFFTX.bit.TXFIFO=1;
SpiaRegs.SPIFFRX.bit.RXFIFORESET=1;
}
interrupt void spiTxFifoIsr(void)
{
SpiaRegs.SPITXBUF=0x4000+temp; //0x0800; // Send data //#########################################################
temp+=0x5;
if(temp==0x1000) {temp=0;}
GpioDataRegs.GPGCLEAR.bit.GPIOG5=1;
GpioDataRegs.GPGSET.bit.GPIOG5=1;
//#########################################################
SpiaRegs.SPIFFTX.bit.TXFFINTCLR=1; // Clear Interrupt flag
PieCtrlRegs.PIEACK.all|=0x20; // Issue PIE ACK
delay(1);
}
interrupt void spiRxFifoIsr(void)
{
Uint16 i;
for(i=0;i<8;i++)
{
rdata[i]=SpiaRegs.SPIRXBUF; // Read data
}
for(i=0;i<8;i++) // Check received data
{
if(rdata[i] != rdata_point+i) error();
}
rdata_point++;
SpiaRegs.SPIFFRX.bit.RXFFOVFCLR=1; // Clear Overflow flag
SpiaRegs.SPIFFRX.bit.RXFFINTCLR=1; // Clear Interrupt flag
PieCtrlRegs.PIEACK.all|=0x20; // Issue PIE ack }
/*******************************************************************************************
函数名称: delay(Uint16 dly)
函数功能: 延时函数
输入参数: 形参dly,dly越大延时越久
输出参数: 无
*******************************************************************************************/
void delay(Uint16 dly)
{
Uint16 i;
for(;dly>0;dly--)
{
for(i=0;i<60000;i++);
}
}
//================================================================================
// No more.
//================================================================================
实验11 IIC 基本通信测试文件
文 件: IicTest.c
标 题: IIC 基本通信测试文件
条 件: 本程序需要DSP281x V1.00头文件支持,另外还需配置成"boot to H0"操作方式。本例IIC
通信数据可在液晶屏上显示。
由于液晶屏是一个低速扩展外设,因此,须将 DSP281x_SysCtrl.c文件中的初始化锁相环
函数InitPll()的实参设置为0x05。
测试:
(1) 将以count为基数的顺序递增数写入外存0x13f000-0x13f800各单元。由下面指令完成:
WriteXram((Uint16 *)0x13f000,0x800);
每执行一次上面的指令,count加1,因此外存0x13f000-0x13f7ff是一个以count起始的动态递
增数组。
(2) 按S16键(键值"F"),将外存0x13f000-0x13f7ff共0x800个字(0x1000个字节)连续存入
24C256 0x00-0x1000共0x1000个字节单元。由下面的程序段完成:
for(n=0;n<0x10;n++)
{
for(m=0;m<4;m++)
{
IIC_WriteNbyte(0xa0,0x00+n,0x00+m*0x40,(Uint16 *)0x13f000,32);
delay(1); // 延时释放总线,否则不能正常传送。
}
}
注意: 考虑到24C256的(100,000次)擦写周期,应避免长时间按"f" 键。另外24C256
是一个慢速器件,写入0x1000个字节需要一点时间。
(3) 按S8键(键值"7"),读取256从0地址开始的0x200个字节数据,并将其放入外存地址
0x12f000-0x12f0ff共0x100个(字)单元. 由下面指令完成:
IIC_ReadNbyte(0xa0,0x00,0x00,(Uint16 *)0x12f000,0x100);
打开View->Memory->0x12f000,可观察从24C256读出的数据。
注意: 由于DSP281x对外存的管理以字(两个字节)为单位,而24C256以字节为单位进行存取。
这里将字的高8位(一个字节)存入24C256的偶数地址,字的低8位 (一个字节)存入
24C256的奇数数地址。因此从24C256读取数据时,建议从偶数地址开始。
(4) 将外存0x13f000开始的44个数据按十进制方式放入Lcd外存(Xram)界面对应44个格子中。 注意: 若出现死机,请打开DSP281x_SysCtrl.c 文件,将初始化锁相环函数InitPll(0x5)中的实参设置为0x4。
*******************************************************************************************/
#include "DSP281x_Device.h" // DSP281x头文件包含文件
#include "DSP281x_Examples.h" // DSP281x范例包含文件
// 通用输入/输出(GPIO)接口宏定义
#define Clk_In GpioMuxRegs.GPBDIR.bit.GPIOB11=0 // 定义Clk_In 为SCL(CPU.71)输入 #define Clk_Out GpioMuxRegs.GPBDIR.bit.GPIOB11=1 // 定义Clk_Out 为SCL(CPU.71)输出 #define Setb_Clk GpioDataRegs.GPBSET.bit.GPIOB11=1 // 定义Setb_Clk 为置SCL(CPU.71)高电平 #define Clr_Clk GpioDataRegs.GPBCLEAR.bit.GPIOB11=1 // 定义Clr_Clk 为置SCL(CPU.71)低电平
#define Dat GpioDataRegs.GPDDAT.bit.GPIOD6 // 定义Dat 为 CPU.83脚,用于接收信号 #define Dat_In GpioMuxRegs.GPDDIR.bit.GPIOD6=0 // 定义Dat_In 为SDA(CPU.83)输入 #define Dat_Out GpioMuxRegs.GPDDIR.bit.GPIOD6=1 // 定义Dat_Out 为SDA(CPU.83)输出 #define Setb_Dat GpioDataRegs.GPDSET.bit.GPIOD6=1 // 定义Setb_Dat 为置SDA(CPU.83)高电平 #define Clr_Dat GpioDataRegs.GPDCLEAR.bit.GPIOD6=1 // 定义Setb_Dat 为置SDA(CPU.83)低电平 #define KEY GpioDataRegs.GPDDAT.bit.GPIOD5 // 定义KEY 为 CPU.79脚,用于接收信号 #define KEY_In GpioMuxRegs.GPDDIR.bit.GPIOD5=0 // 定义KEY_In 为KEY(CPU.79)输入 /*******************************************************************************************
注意:有关液晶屏显示的函数原型声明都放在 DSP281x_GlobalPrototypes.h 文件中 *******************************************************************************************/
// 函数原型声明,以下10个函数来自本文件。
void WriteXram();
// 从指定的外存地址StartAddr开始到EndAddr结束,顺序写入number数据。
// 函数原型声明,以下6个函数来自Bc7281.c文件。
void Write_7281(); // 向7281写入一个字节的数据。
uchar Read_7281(); // 从BC7281读出一个数据字节。 void IIC_WriteNbyte();
// 将外存地址0x13f110开始的N个数据,发送到256从地址为(suba2,suba1)的N个单元。 uchar IIC_ReadNbyte();
// 读取256某子地址开始的N个字节数据,并将其放入外存地址0x13f12c开始的N个单元。 void LedH_Display();
// 将模数转换值以16进制两个字节形式,在Led第8,7,6,5位数码管上进行显示。 void LedD_Display();
// 将模数转换值以10进制形式,在Led第8,7,6,5位数码管上进行显示。 void delay(Uint16 dly);
// 全局变量声明
extern uchar ack; // ack是在进行IIC通信时设置的一个变量。当IIC通信正常时,置ack=0xAA,
// 否则置ack=0x55。本文件在调用Write_7281()函数时要用到这个值。以
// 便在右数第三、第四个LED数码管上显示。
uchar key_number; // key_number为从BC7281读出的按键键值。该键值在右数第一、第二个LED
// 数码管上显示。
Uint16 count=0;
void main()
{
Uint16 m,n;
// 步骤1 系统控制初始化:
InitSysCtrl(); // 锁相环(PLL),看门狗(WatchDog)及外设时钟(PeripheralClocks)初始化。
// 这个函数由DSP281x_SysCtrl.c文件建立。
// 步骤2。初始化GPIO
// InitGpio()函数例举怎样将GPIO设置成其默认状态,该函数由DSP281x_Gpio.c文件建立。
// InitGpio(); // 本例跳过这个函数。
// 步骤3 关所有中断并初始化PIE向量表:
DINT; // 关CPU中断。
//InitPieCtrl(); // 初始化PIE控制寄存器为默认状态,该状态关所有PIE中断并清所有
// PIE中断标识符。 InitPieCtrl()函数由DSP281x_PieCtrl.c文件建立。
IER = 0x0000;
IFR = 0x0000; // 关CPU中断并清所有CPU中断标识符。
//InitPieVectTable(); // 本例不跳过这个函数。
// 初始化PIE向量表,该向量表指明了中断服务程序(ISR)的一种构架。
// 即使在这个示例中用不到中断,仍板上组装了整个PIE向量表。作为调试
// 目的这是很有用的。ISR程序架构由DSP281x_DefaultIsr.c文件建立。
// InitPieVectTable()函数由DSP281x_PieVect.c文件建立。
// 步骤4 初始化器件外设: InitPeripherals()函数由DSP281x_InitPeripherals.c文件建立。
//InitPeripherals(); // 本例不跳过这个函数。
// 步骤5 用户绝对代码,中断使能,使能PIE中的ADCINT。
// 将0写入外存0x13f000-0x140000诸单元。
lcd_init(); // Lcd 初始化
clearscr1(); // 清除第一显示缓冲区:0x0000-0x29ff
clearscr2(); // 清除第二显示缓冲区:0x2a00-0x53ff
clearscr3(); // 清除第三显示缓冲区:0x5400-0x7FFF
Disp_XramTab(); // 为外存(Xram)Lcd界面制作表格
delay(5);
EALLOW; // 允许访问受保护的空间
Clk_Out; // 设定连接CLKK(7281.3)的SCL
// (TDIRB"CPU.71")为输出(时钟脉冲输出)
Dat_In; // 设定连接DATT(7281.1)的SDA
// (T4CTRIP"CPU.83")为输入(接收7281的反馈信号)
EDIS; // 禁止访问受保护的空间
Setb_Clk;
Write_7281(0x12,0x84); // 初始化BC728x
EALLOW; // 允许访问受保护的空间
KEY_In; // 设定KEY(CPU.79)为输入
EDIS; // 禁止访问受保护的空间
for(;;) // 无限循环
{
WriteXram((Uint16 *)0x13f000,0x800);
// 将顺序递增数count写入外存0x13f000-0x13f800各单元。
//DispXram_D((Uint16 *)0x13f000);
// 将外存0x13f000开始的44个数据按十进制方式放入Lcd外存
// (Xram)界面对应44个格子中显示。
DispXram_H((Uint16 *)0x13f000);
// 将外存0x13f000开始的44个数据按十六进制方式放入Lcd外
// 存(Xram)界面对应44个格子中显示。
//LedD_Display((Uint16 *)0x13f000);
// 左面4个LED数码管以十进制显示外存地址0x13f000中的数据。
LedH_Display((Uint16 *)0x13f000);
// 左面4个LED数码管以十六进制显示外存地址0x13f000中的数据。
delay(3);
if(KEY==0) // 当BC7281接收到有效按键时,将KEY(CPU.79脚)置为低电平()。
// 即:有键按下,KEY=0;无键按下,KEY=1
// 有按键(if条件等于1,为真) 进入下层,判别按键值。
// 无按键(if条件等于0,为假) 进入else,读出按键值。
// 即有键按下时,读出按键值;当没有按键时,判别前一个按键值
{
key_number=Read_7281(0x13); // 读出按键字值。
switch(key_number) // 无按键(KEY=1),判别前一个按键值。
{
case 0x0f: // 按键值为0x0f. S16键
{
// 注意:ack&0x0f须加括号(),否则在最低位显示
Write_7281(0x15,0x10+(key_number&0xf0)/16);
Write_7281(0x15,key_number&0x0f);
// 将外存0x13f000-0x13f7ff共0x800个字(0x1000个字节)连续
// 存入24C256 0x00-0x1000共0x1000个字节单元。
for(n=0;n<0x10;n++) // 大循环,控制24C256子地址高8位。
{
for(m=0;m<4;m++) // 小循环,控制24C256子地址低8位。
{
IIC_WriteNbyte(0xa0,0x00+n,0x00+m*0x40,(Uint16 *)0x13f000,32);
// 这里第4个实参32的单位为字共64个字节。24C256页写规
// 定为64个字节。大于64个字节,地芳剖?
// 先前写的数据将被覆盖。
delay(1); // 延时释放总线,否则不能正常传送。
}
}
delay(3);
Write_7281(0x15,0x30+((ack&0xf0)/16));
// 在右起第4个Led?
// 高4位
Write_7281(0x15,0x20+(ack&0x0f));
// 在右起第3个Led数码管上显示按键字节值
// 低4位.
// 若IIC通信正常显示"AA",否则显示"55"
} break;
case 0x00: // 按键值为0,S1键
{
Write_7281(0x15,0x30+((ack&0xf0)/16));
// 在第2个Led数码管上显示按键字节值高4位
Write_7281(0x15,0x20+(ack&0x0f));
// 注意:ack&0x0f须永ê?),否则在0位显示
delay(3);
} break;
case 0x07: // 按键值为7,S8键
{
Write_7281(0x15,0x10+(key_number&0xf0)/16);
// 在第2个Led数码管上显示按键字节值高4位
Write_7281(0x15,key_number&0x0f);
// 在第1个Led数码管上显示按键字节值低4位
IIC_ReadNbyte(0xa0,0x00,0x00,(Uint16 *)0x12f000,0x100);
// 读取256从0地址开始的0x200个字节数据,并将其放入外存地址
// 0x12f000-0x12f0ff共0x100个(字)单元.
delay(3);
Write_7281(0x15,0x30+((ack&0xf0)/16));
// 在右起第4个Led数码管上显示按键字节值
// 高4位
Write_7281(0x15,0x20+(ack&0x0f));
// 在右起第3个Led数码管上显示按键字节值
// 低4位.
// 若IIC通信正常显示"AA",否则显示"55"
} break;
default: // 其他按键的处理.
{
Write_7281(0x15,0x30+((ack&0xf0)/16));
// 在第2个Led数码管上显示按键字节值高4位
Write_7281(0x15,0x20+(ack&0x0f));
// 注意:ack&0x0f须加括号(),否则在0位显示
delay(3);
}
}
}
else // 若有按键(KEY=0),则读出按键值,并将按键
// 的字节值在第2,第1个Led数码上显示
{
key_number=Read_7281(0x13); // 读出按键字值。
Write_7281(0x15,0x10+(key_number&0xf0)/16);
// 在第2个Led数码管上显示按键字节值高4位
Write_7281(0x15,key_number&0x0f);
// 在第1个Led数码管上显示按键字节值低4位
}
}
}
/*******************************************************************************************
函数名称: WriteXram(Uint16 *StartAddr, Uint16 number) 函数功能: 将number个count(初始值为0)顺序递增数写入始地址为StartAddr的number个单元 输入参数: 第一形参StartAddr为一指针变量,要写入数据的首地址。
第二形参number要写入数据的个数。
输出参数: 无
*******************************************************************************************/
void WriteXram(Uint16 *StartAddr, Uint16 number) {
Uint16 i,j;
j=count;
for(i=0;i0;dly--)
{
for(i=0;i<100000;i++);
}
}
//================================================================================
// No more.
//================================================================================
附:Iic_Bottom.c程序
函数:Iic_Bottom.c
主器件(CPU)与从器件24C256(器件地址为0xa0,256K bit)之间通过IIC总线通信的几个要点: (1)总线上数据的有效性:
IIC总线数据传输时,在时钟线高电平期间数据线上必须保持稳定的逻辑电平状态,高电平为数据
1,低电平为数据0。只有在时钟线为低电平时,才允许数据线上的电平状态变化。 (2)IIC总线的启动:
在时钟线保持高电平期间,数据线出现由高电平向低电平的变化时,启动IIC总线。 (3)IIC总线的终止:
在时钟线保持高电平期间,数据线出现由低电平向高电平的变化时,终止IIC总线。 (4)主器件(CPU)向从器件传送一个字节数据(见IIC_SendByte()):
它可分成如下三个步骤:
第一步: 由主器件(CPU)发出IIC总线启动信号;
第二步: 待发送的字节数据可以是从器件地址(指令),或从器件子地址,或数据。从高位
到低位逐位取出位数据,若为1,置数据线为高电平,若为0,则置数据线为低电
平。每一位数据的传送通过时钟线的一个正脉冲完成;
第三步: 当8个位数据传送完毕,主器件(CPU)将接收从器件的应答信号,见(4),以便判断
从器件接收是否正常。
(5)从器件的应答:
主器件向从器件传送一个字节数据后,从器件都必须产生一个应答信号。信号在第9个时钟
周期将数据线拉低,表示已收到一个8位数据。
(6)从器件24C256向主器件(CPU)传送一个字节数据(见IIC_ReceiveByte()):
当从器件24C256工作于读模式时,它由以下三个步骤组成:
第一步: 从器件24C256将待读取的一个字节数据从高位到低位逐位取出位数据,若为
1,从器件置数据线为高电平,否则置数据线为低电平。每一位数据的发送都通过
主器件在时钟线上产生的一个正脉冲完成;
第二步: 8位数据发送完毕,从器件释放数据总线,并监视主器件的一个应答信号;
第三步: 从器件一旦收到应答信号,则继续发送数据,否则从器件停止发送数据并等待一
个停止信号。
(7)主器件的应答信号:
*******************************************************************************************/
#include "DSP281x_Device.h" // DSP281x 头文件包含文件
#include "DSP281x_Examples.h" // DSP281x 示例包含文件
/*******************************************************************************************
模拟 IIC 接口线定义:
这里设置了J17插座,24C256的时钟线SCL通过跳线可以选择DSP281x的TDIRA引脚或者T1CTRIP引脚。
当跳线连接TDIRA引脚时,选择有关GPIOA11的4条指令并屏蔽有关GPIOD0的4条指令。
当跳线连接T1CTRIP引脚时,选择有关GPIOD0的4条指令并屏蔽有关GPIOA11的4条指令。 ******************************************************************************************/
#define SDA GpioDataRegs.GPDDAT.bit.GPIOD1 //定义SDA 为 CPU.115脚,用于接收信号
#define SDA_In GpioMuxRegs.GPDDIR.bit.GPIOD1=0 //定义SDA_In 为SDA(CPU.115)输入 #define SDA_Out GpioMuxRegs.GPDDIR.bit.GPIOD1=1 //定义SDA_Out 为SDA(CPU.115)输出 #define Setb_SDA GpioDataRegs.GPDSET.bit.GPIOD1=1 //定义Setb_SDA 为置SDA(CPU.115)高电平 #define Clr_SDA GpioDataRegs.GPDCLEAR.bit.GPIOD1=1 //定义Setb_SDA 为置SDA(CPU.115)低电平 #define SCL_In GpioMuxRegs.GPADIR.bit.GPIOA11=0 //定义SCL_In 为SCL(CPU.110)输入 #define SCL_Out GpioMuxRegs.GPADIR.bit.GPIOA11=1 //定义SCL_Out 为SCL(CPU.110)输出 #define Setb_SCL GpioDataRegs.GPASET.bit.GPIOA11=1 //定义Setb_SCL 为置SCL(CPU.110)高电平 #define Clr_SCL GpioDataRegs.GPACLEAR.bit.GPIOA11=1 //定义Clr_SCL 为置SCL(CPU.110)低电平 uchar ack; // 声明count_为外部变量,否则不能引用 Uint16 number=0;
void IIC_Ack(uchar j);
/*******************************************************************************************
函 数: IIC_SendByte(uchar send_byte)
输入参数: uchar send_byte为待发送的字节
输出参数: 无
功能: 主器件CPU向24C256发送一个字节(地址或数据),发完后等待从器件应答。若正常,从
器
件应答方式为:将SDA线置成低电平; 否则从器件不予应答,SDA线仍保持原来的高电平。
如果数据发送正常置ack=0xaa,否则置ack=0x55.
关于使用2812某个I/O口的说明:
在使用2812某个I/O口之前,要声明该口是用作输入还是输出口,
例如:SCL_Out;将SCL口作为输出口,又如:SDA_In; 将SDA口作为输入口,等等. *******************************************************************************************/
void IIC_SendByte (uchar send_byte)
{
unsigned int bit_counter;
EALLOW; // 允许访问受保护的空间
SCL_Out; // 设定时钟线SCL为输出
SDA_Out; // 设定数据线SDA为输出
EDIS; // 禁止访问受保护的空间
for(bit_counter = 0; bit_counter < 8; bit_counter++)//发送8位
{
if((send_byte<>8); // 取高8位字节存入256
IIC_SendByte(j&0x00ff); // 取低8位字节存入256
}
IIC_Stop();
return(1); // IIC通信正常,把控制返回给调用函数。
}
/*******************************************************************************************
函数: IIC_ReadByte(uchar sla,uchar data)
输入参数: 第一形参 uchar sla 为从器件地址
第二形参 uchar data 为需发送的数据
输出参数: 无
功能: 向无子地址器件读取一个字节数据
*******************************************************************************************/
uchar IIC_ReadByte(uchar sla)
{
//Uint16 i;
IIC_Start(); // 启动总线
IIC_SendByte(sla+1); // 发送从器件地址
if(ack==0x55) return(0);
//i=IIC_ReceiveByte(); // 读取数据
IIC_Ack(1); // 发送非应答信号
IIC_Stop(); // 结束总线
return(1);
}
/*******************************************************************************************
函 数: IIC_ReadNbyte(uchar sla,uchar suba1,uchar suba2, Uint16 *Xaddr, uchar k)
输入参数: 第一形参 uchar sla 为从器件256地址
第二形参 uchar suba1 为从器件256高8位子地址
第三形参 uchar suba2 为从器件256低8位子地址
第四形参 Uint16 *Xaddr 为一个指针变量Xaddr,为拷入存储器目标首地址。
第五形参 uchar data 为需发送的数据
输出参数: 在调用IIC传送函数时,若应答ack=0xAA,则IIC通信正常,返回值为1;
若应答ack=0x55,则IIC通信失败,返回值为0。
功 能: 读取256某子地址开始的2k个字节数据,并将其放入外存地址Xaddr开始的k个(字)单元 *******************************************************************************************/
uchar IIC_ReadNbyte(uchar sla,uchar suba1,uchar suba2,Uint16 *Xaddr,uchar k)
{
uchar i;
Uint16 h,l;
IIC_Start(); // 启动总线
IIC_SendByte(sla); // 发送从器件地址
if(ack==0x55) return(0);
IIC_SendByte(suba1);
if(ack==0x55) return(0); // 发送从器件高8位子地址
IIC_SendByte(suba2);
if(ack==0x55) return(0); // 发送从器件低8位子地址
IIC_Start(); // 第二次启动总线
IIC_SendByte(sla+1); // 发送从器件读指令
if(ack==0x55) return(0);
for(i=0;i43) {Offset=0xffff;}
Offset++; // 偏移量的有效值范围为[0,43]
X_addr=(Uint16 *)0x0013f000+Offset;
// 将外存地址0x0013f000+Offset赋值给
// 指针变量X_addr。
data=*X_addr; // 将外存地址X_addr中的数据存入data。
delay(2); // 延时
} break;
case 0x08: // 按键值为8,偏移量跟踪按键8的次数。
// 以便光标在44个数据格中的定位。
{
if(Offset<1) {Offset=44;}
Offset--; // 偏移量的有效值范围为[0,43]
X_addr=(Uint16 *)0x0013f000+Offset;
// 将外存地址0x0013f000+Offset赋值给
// 指针变量X_addr。
data=*X_addr; // 将外存地址X_addr中的数据存入data。
delay(2); // 延时
} break;
case 0x07: // 按键值为0,模数转换值以十进制显示
{
X_addr=(Uint16 *)0x0013f000+Offset;
// 将外存地址0x0013f000+Offset赋值给
// 指针变量X_addr。
data=*X_addr; // 将外存地址X_addr中的数据存入data。
*X_addr=data+10; // 将数据data+10存入外存X_addr地址中(
delay(1); // 延时
} break;
case 0x0F: // 按键值为0,模数转换值以十进制显示
{
X_addr=(Uint16 *)0x0013f000+Offset;
// 将外存地址0x0013f000+Offset赋值给
// 指针变量X_addr。
data=*X_addr; // 将外存地址X_addr中的数据存入data。
*X_addr=data-10; // 将数据data-10存入外存X_addr地址中(
delay(1); // 延时
} break;
default: // 其他按键的处理同按键值0x00
{
LedD_Display();
}
}
}
else // 无按键(KEY=,)
{
Write_7281(0x15,0x10+(key_number&0xf0)/16);
// 在第2个Led数码管上显示按键字节值高4位
Write_7281(0x15,key_number&0x0f);
// 在第1个Led数码管上显示按键字节值低4位
LedD_Display(); // 在左边4个数码管上以10进制显示data动态数值.
}
}
}
/******************************************************************************
函数名称: IntXram(Uint16 *StartAddr, Uint16 *EndAddr) 函数功能: 从指定的外存地址StartAddr开始到EndAddr结束,顺序写入0x0000数据。
若将指令 *StartAddr++ =0x0000; 改成 *StartAddr++ =count++; 调用该函保?
可?StartAddr++ =number++;指令前设置断点,打开对应的Memory窗口,按F10键,
可看出 number 数据递增写入对应单元。
输入参数: 第一形参StartAddr为一指针变量,要写入数据的首地址。
第二形参EndAddr为一指针变量,要写入数据的结束地址。
第三形参number为写入的数据。
输出参数: 无
******************************************************************************/
void IntXram(Uint16 *StartAddr, Uint16 *EndAddr) {
while(StartAddr0;dly--)
{
for(i=0;i<100000;i++);
}
}
//================================================================================ // No more.
//===================================================================== ===========
实验12 LCD测试程序
文 件: LCD_TEST.C
说 明: LCD_TEST.C 是一个关于LCD液晶屏作图及汉字显示的文件。它包含下列作图:
(1) 画园内接不规则多边形
(2) 秒针线簇
(3) 作过中心点的射线簇
(4) 画圆曲线簇
(5) 画椭圆曲线簇
(6) 画正弦曲线簇
(7) 汉字显示王安石词 桂枝香词
*******************************************************************************************/
#include "DSP281x_Device.h" // DSP281x 头文件包含文件 #include "DSP281x_Examples.h" // DSP281x 示例包含文件 #include "math.h"
Uint16 *Tab=(Uint16 *) 0x100000; void delay();
void pentacle();
void radial(); // 过中心点的射线簇 void Line(); // 过中心点的直线簇 void DispChar(); // 在不同的显示缓冲区存储数字和汉字,并删除 void CircleCurve(); // 画圆曲线簇
void EllipseCurve(); // 画椭圆曲线簇
void Sine_Curve(); // 画正弦曲线簇
void Poem_from_WhanAnShi(); // 王安石词 桂枝香
void TrCurve();
void circle(); // 画一个圆
void ellipse(); // 画一个椭圆
void SineCurve(); // 画一个周期的正弦曲线
// 以下7个函数构成外存Lcd界面
void XramInterface(); // 液晶屏显示外存(Xram)界面,一屏可显示外存80个字节 void WriteXram(); // 向外存写顺序数据
void XramOrder(); // 显示外存Lcd界面顶头两行"0-f"16个升序数字 void XramTab(); // 为外存(Xram)Lcd界面制作表格
void DispCharacter(); // 为外存(Xram)Lcd界面制作填写字符 void DispXramAddress(); // 显示外存从地址(Address)开始的80个字节数据 void DispXram_(); // 将外存80个数据放入Lcd外存(Xram)界面对应80个格子 Uint16 analog=0; // 模拟量analog为全局变量,可被主函数及主函数之外的函数引用 Uint16 *Tab; // 指针*Tab为全局变量,可通过"Tab=(Uint16 *)0x xx;"赋予外存xx地址 Uint16 count;
void main(void)
{
InitSysCtrl(); // 初始化系统
DINT; // 关中断
IER = 0x0000;
IFR = 0x0000;
count=9999;
//InitPieCtrl(); // 初始化PIE
//InitPieVectTable(); // 初始化PIE中断矢量表
//InitPeripherals(); // 初始化外设
lcd_init();
clearscr1(); // 第一显示缓冲区(0x0000-0x29ff)清零
clearscr2(); // 第二显示缓冲区(0x2a00-0x53ff)清零
clearscr3(); // 第三显示缓冲区(0x5400-0x7dff)清零
for(;;)
{
pentacle(); // 在第一显示区,画过中心点的五角星
radial(); // 在第一显示区,画过中心点的射线簇
clearscr1();
//clearscr2(); // 第二显示缓冲区(0x2a00-0x53ff)清零
//clearscr3(); // 第三显示缓冲区(0x5400-0x7dff)清零
Line(); // 在第一显示区,画过中心点的直线簇
clearscr1(); // 第一显示缓冲区(0x0000-0x29ff)清零
clearscr2(); // 第二显示缓冲区(0x2a00-0x53ff)清零
clearscr3(); // 第三显示缓冲区(0x5400-0x7dff)清零
CircleCurve(); // 在第一显示区,画圆曲线簇
clearscr1(); // 第一显示缓冲区(0x0000-0x29ff)清零
EllipseCurve(); // 在第一显示区,画椭圆曲线簇
clearscr1(); // 第一显示缓冲区(0x0000-0x29ff)清零
Sine_Curve(); // 在第一显示区,画正弦曲线簇
clearscr1(); // 第一显示缓冲区(0x0000-0x29ff)清零
Poem_from_WhanAnShi(); // 在第一显示区,显示王安石词 桂枝香
delay(1000); // 长延时
clearscr1(); // 第一显示缓冲区(0x0000-0x29ff)清零
}
}
/*******************************************************************************************
函数名称: DispChar(Uint16 k)
函数功能: 在不同的显示缓冲区存储数字和汉字,并删除,以便了解不同显示域的概念 输入参数: 第一形参y,第y行为40个数字的显示行,第(y+17)为20个汉字的显示行
第二形参k,当k=0,删除一行数字,否则删除一行汉字
输出参数: 无
*******************************************************************************************/
void DispChar(Uint16 y,Uint16 k) {
Uint16 i,j=0;
while(j!=4)
{
for(i=0;i<10;i++)
{ Display2(i,10*j+i,y,1,1); } // 数字存储在第一显示缓冲区
j++;
}
for(i=0;i<20;i++)
{ Display2(500+i,2*i,y+17,1,2); } // 汉字存储在第二显示缓冲区
j=0;
while(j!=4)
{ for(i=0;i<10;i++)
{ Display2(i,10*j+i,y+34,0,3); } // 数字存储在第三显示缓冲区
j++;
}
for(i=0;i<20;i++)
{ Display2(500+i,2*i,y+51,0,3); } // 汉字存储在第三显示缓冲区
delay(100);
if(k==0) clearscr1(); // 仅删除第一显示域一行数字
else clearscr2(); // 仅删除第二显示域一行汉字 }
/*******************************************************************************************
函数名称: pentacle(void)
函数功能: 画过中心点的五角星
输入参数: 无
输出参数: 无
*******************************************************************************************/
void pentacle(void)
{
Uint16 i,x,y,a,b;
double p=2*0.008726546258;
for(i=0;i<5;i++) // 五角星
{
x=160+(int)100*cos(144*i*p);
y=120+(int)100*sin(144*i*p);
a=x;
b=y;
x=160+(int)100*cos(144*(i+1)*p);
y=120+(int)100*sin(144*(i+1)*p);
liner(a,b,x,y,1);
delay(50);
}
/*
for(i=0;i<18;i++)// 18 角星
{
x=160+(int)100*cos(140*i*p);
y=120+(int)100*sin(140*i*p);
a=x;
b=y;
x=160+(int)100*cos(140*(i+1)*p);
y=120+(int)100*sin(140*(i+1)*p);
liner(a,b,x,y,1);
delay(50);
}
*/
}
/*******************************************************************************************
函数名称: radial(void)
函数功能: 画过中心点的射线簇
输入参数: 无
输出参数: 无
*******************************************************************************************/
void radial(void)
{
Uint16 i,x,y;
double p=2*0.008726546258;
for(i=0;i<360;i+=5)
{
x=160+(int)100*cos(i*p);
y=120+(int)100*sin(i*p);
liner(160,120,x,y,1);
delay(10);
}
}
/*******************************************************************************************
函数名称: Line(void)
函数功能: 画过中心点的直线簇
输入参数: 无
输出参数: 无
*******************************************************************************************/
void Line(void)
{
Uint16 i;
for(i=0;i<330;i+=10)
{
liner(i,0,320-i,240,1);
delay(10);
}
for(i=0;i<240;i+=10)
{
liner(0,240-i,320,i,1);
delay(10);
}
}
/*******************************************************************************************
函数名称: CircleCurve(void) 函数功能: 画圆曲线簇
输入参数: 无
输出参数: 无
*******************************************************************************************/
void CircleCurve(void) {
Uint16 i,k=0;
while(k<3)
{
for(i=0;i<80;i+=5)
{
circle(120+i,84+i,80);
delay(10);
}
clearscr1();
k++;
}
}
/*******************************************************************************************
函数名称: CircleCurve(void) 函数功能: 画椭圆曲线簇
输入参数: 无
输出参数: 无
*******************************************************************************************/
void EllipseCurve(void) {
Uint16 i,k=0;
while(k<3)
{
for(i=0;i<80;i+=5)
{
ellipse(160,120,50+i,10+i);
delay(10);
}
clearscr1();
k++;
}
}
/*******************************************************************************************
函数名称: EllipseCurve(void)
函数功能: 画正弦曲线簇
输入参数: 无
输出参数: 无
*******************************************************************************************/
void Sine_Curve(void)
{
Uint16 i,k=0;
while(k<3)
{
for(i=0;i<=120;i+=5)
{
SineCurve(i,120,80,40);
delay(10);
}
clearscr1();
k++;
}
}
/*******************************************************************************************
函数名称: Poem_from_WhanAnShi(void) 函数功能: 王安石词 桂枝香
输入参数: 无
输出参数: 无
*******************************************************************************************/
void Poem_from_WhanAnShi(void) {
DrawArea(1,1,320,240,1);
DrawArea(2,2,319,239,1);
ShowWord(500,1);
}
/*******************************************************************************************
函数名称: WriteXram(Uint16 StartNum,Uint16 sum)
函数功能: 向外存写顺序数据
输入参数: 第一形参StartNum,为开写的第一个数据
第一形参sum,为要写入的总数
输出参数: 无
*******************************************************************************************/
void WriteXram(Uint16 StartNum,Uint16 sum)
{
Uint16 i;
for(i=0;i0;dly--)
for(i=0;i<50000;i++);
}
/*******************************************************************************************/ /******************************************************************************************* 函数名称: XramInterface()
函数功能: 外存(Xram)Lcd界面,一屏可显示外存80个字节
输入参数: 无
输出参数: 无
*******************************************************************************************/ /*******************************************************************************************/ void XramInterface()
{
Tab=(Uint16 *) 0x100000; // 初始化Tab指针
WriteXram(0,0xffff);
XramTab();
DispCharacter();
Tab=(Uint16 *) 0x100000;
DispXramAddress();
}
/******************************************************************************************* 函数名称: XramTab(void)
函数功能: 为外存(Xram)Lcd界面制作表格
输入参数: 无
输出参数: 无
*******************************************************************************************/ void XramTab(void)
{
Uint16 i;
DrawArea(1,1,320,240,2);
DrawArea(4,4,316,236,2);
for(i=0;i<=8;i++)
{
DrawaVertical(60+32*i,4,236, 2);
}
DrawaLevel(25,60,316,2);
for(i=0;i<=10;i++)
{
DrawaLevel(46+19*i,4,316,2);
}
XramOrder(6,16,21,0);
}
/*******************************************************************************************
函数名称: XramOrder(Uint16 y,Uint16 num,Uint16 dist,Uint16 cond) 函数功能: 显示外存Lcd界面顶头两行"0-f"16个升序数字
输入参数: 第一形参y,水平方向定位坐标
第二形参num,待写数字的个数
第三形参distance,行间距
第四形参condition,数字要写入的显示域
输出参数: 无
*******************************************************************************************/
void XramOrder(Uint16 y,Uint16 num,Uint16 dist,Uint16 cond) {
Uint16 i,k;
for(i=0;i 0)
{
y--; // y减量取点
dot(x,y,2); // 第1点P(x,y), 右下角,
// 画第一象限靠y轴的1/8园弧上的点
dot(x0+y-y0,y0+x-x0,2); // 第2点P1x, 右下角,
// 是第1点P关于y=x轴在第1象限的对称点
dot(x0-y+y0,y0+x-x0,2); // 第3点P2x, 左下角,
// 是第2点P1x关于x=0轴在第2象限的对称点
dot(x0+y-y0,y0-x+x0,2); // 第4点P4x, 右上角,
// 是第2点P1x关于y=0轴在第4象限的对称点
dot(x0-y+y0,y0-x+x0,2); // 第5点P3x, 左上角,
// 是第4点P4x关于x=0轴在第3象限的对称点
dot(2*x0-x,y,2); // 第6点P2y, 左下角,
// 是第1点P关于x=0轴在第2象限的对称点
dot(2*x0-x,2*y0-y,2); // 第7点P3y, 左上角,
// 是第6点P2y关于y=0轴在第3象限的对称点
dot(x,2*y0-y,2); // 第8点P4y, 右上角,
// 是第1点P关于y=0轴在第4象限的对称点
}
else // y无减量取点
{
dot(x,y,2); // 第1点P(x,y), 右下角,
// 画第一象限靠y轴的1/8园弧上的点
dot(x0+y-y0,y0+x-x0,2); // 第2点P1x, 右下角,
// 是第1点P关于y=x轴在第1象限的对称点
dot(x0-y+y0,y0+x-x0,2); // 第3点P2x, 左下角,
// 是第2点P1x关于x=0轴在第2象限的对称点
dot(x0+y-y0,y0-x+x0,2); // 第4点P4x, 右上角,
// 是第2点P1x关于y=0轴在第4象限的对称点
dot(x0-y+y0,y0-x+x0,2); // 第5点P3x, 左上角,
// 是第4点P4x关于x=0轴在第3象限的对称点
dot(2*x0-x,y,2); // 第6点P2y, 左下角,
// 是第1点P关于x=0轴在第2象限的对称点
dot(2*x0-x,2*y0-y,2); // 第7点P3y, 左上角,
// 是第6点P2y关于y=0轴在第3象限的对称点
dot(x,2*y0-y,2); // 第8点P4y, 右上角,
// 是第1点P关于y=0轴在第4象限的对称点
}
}
}
/*******************************************************************************************
函数名称: ellipse(Uint16 m,Uint16 n,Uint16 a,Uint16 b) 函数功能: 画以(m,n)为中心,长轴(x轴)为a,短轴(y轴)为b的一个椭圆
输入参数: 第一形参m与第二形参n,构成椭圆中心坐标(m,n)
第三形参为长轴(x轴)a
第四形参为短轴(y轴)b
输出参数: 无
注 意: 有效椭园须在液晶屏内,园为椭圆的一个特例,可用该函数画圆,只需令:
a=b=r 画椭圆的速度较画圆的速度慢
*******************************************************************************************/
void ellipse(Uint16 m,Uint16 n,Uint16 a,Uint16 b) {
int i;
int x,y;
double p=0.008726546258;
// p=pi=3.1415926535/360
for(i=1;i<180;i++) // 当i=180时,i*p=pi/2=3.1415926535/2
{
x=m+(int)a*sin(i*p);
y=n+(int)b*cos(i*p);
dot(x,y,2); // 第1点,画第一象限(右下角)靠y轴的1/4园弧上的点
dot(2*m-x,y,2); // 第2点,是第1点关于x=0轴在第2象限(左下角)的对称点
dot(x,2*n-y,2); // 第3点,是第1点关于y=0诘?象限(右上角)的对称点
dot(2*m-x,2*n-y,2); // 第4点,是第1点关于y=-x轴在第3象限(左上角)的对称点
}
}
/*******************************************************************************************
函数名称: SineCurve(Uint16 x0,Uint16 y0,Uint16 h,Uint16 l)
函数功能: 画一个周期的正弦曲线
输入参数: 第一形参x0与第二形参y0,构成正弦曲线的起点
第三形参h为正弦曲线的高度
第四形参l与周期T的关系为: T=4*l 输出参数: 无
*******************************************************************************************/
void SineCurve(Uint16 x0,Uint16 y0,Uint16 h,Uint16 l)
{
int i,k;
int x,y;
double j;
double p=0.008726546258;// p=pi=3.1415926535/360
//double p=0.017453292;
//float k;
//k=l/180; // 为何此处定义之后,循环语句调用不行?
if(l>=60) k=720;
else k=360;
for(i=0;i=60) j=i*p;
else j=2*i*p;
if(l>=60)
x=x0+(int)((i*l)/180);
else
x=x0+(int)((i*l)/90);
y=y0+(int)h*sin(j);
dot(x,2*y0-y,2); // 第1点,画第一象限(右下角)靠y轴的1/4园弧上的点
//dot(l+x,y,2);
//dot(2*l+x,2*y0-y,2);
//dot(3*l+x,y,2);
dot(4*l+x,2*y0-y,2);
//delay(2);
}
}
void TrCurve()
{
Uint16 i;
for(i=0;i<64;i++)
{ dot(32+i,120-i,1); }
for(i=0;i<64;i++)
{ dot(95+i,57+i,1); }
for(i=0;i<64;i++)
{ dot(158+i,120-i,1); }
for(i=0;i<64;i++)
{ dot(221+i,57+i,1); }
}
// dot(Uint16 x, Uint16 y, Uint16 partition)
//================================================================================ // No more.
//================================================================================
实验13 ADC实验
一、ADCSOC实验
********************************************************************************************
文件: Example_281xAdcSoc.c
标题: DSP281x ADC Example Program. 说明: 这个程序需要V1.00头文件支持。另外,该项目需要配置成"boot to H0"操作方式。
在编译这个示例之前,确保CPU时钟与DSP281x_Examples.h定义的时钟相匹配。将信号连接到
A2及A3通道进行转换
本例将锁相环PLL设置成 x10/2 模式,系统时钟6分频得到一个25Mhz高速外设时钟HSPCLK (假
定晶振为30Mhz)。在ADC模块中这一个时钟不用再进行分频,即ADC采用25Mhz的高速外设时钟
HSPCLK。使能中断并将事件管理器A(EVA)设置成产生一个SEQ1的周期ADC SOC。使用ADCINA3
及ADCINA2两个通道进行转换。
观察变量:
Voltage1[10] ADC结果寄存器0(ADCRESULT0)最后10个值
Voltage2[10] ADC结果寄存器1(ADCRESULT1)最后10个值
ConversionCount 当前结果数0-9
LoopCount 空循环计数器
//******************************************************************************************
#include "DSP281x_Device.h" // DSP281x 头文件包含文件 #include "DSP281x_Examples.h" // DSP281x 示例包含文件
// 由本文件建立的函数原型声明
interrupt void adc_isr(void); // ADC中断服务函数
void OscillographTable();
// 本例中的全局变量
Uint16 LoopCount; // 循环计数器
Uint16 ConversionCount; // 转换计数器
Uint16 Voltage1[256]; // 电压缓冲器1
//Uint16 Voltage2[10]; // 电压缓冲器2
void AdcAverage();
void VoltageCurve();
void AdcResultCopy();
void liner();
void delay(Uint16 dly);
Uint16 *Xaddr=(Uint16 *)0x13f000; Uint16 Xram_pointer=0;
main()
{
// 步骤1. 系统控制初始化: PLL, WatchDog, 使能外设时钟。
// 这个示例函数在DSP281x_SysCtrl.c文件中建立
InitSysCtrl();
lcd_init();
clearscr1(); // 第一显示缓冲区(0x0000-0x29ff)清零
clearscr2(); // 第二显示缓冲区(0x2a00-0x53ff)清零
clearscr3(); // 第三显示缓冲区(0x5400-0x7dff)清零
OscillographTable(); // 制作示波器表格
// 本例设置高速外设时钟HSPCLK为系统时钟SYSCLKOUT的6分频。在系统时钟为150Mhz
// 的条件下,高速外设时钟HSPCLK为25Mhz。
EALLOW; // 允许访问受保护的寄存器
SysCtrlRegs.HISPCP.all = 0x3; // HSPCLK = SYSCLKOUT/6
EDIS; // 禁止访问受保护的寄存器
// 步骤2. 初始化GPIO。这个示例函数由DSP281x_Gpio.c文件建立,例举如何将GPIO设置成
// 其默认状态
// InitGpio(); // 本例跳过这个函数
// 步骤3. 清除所有中断及初始化PIE向量表:
DINT; // 禁止可屏蔽中断(置INTM位)
// 初始化PIE控制寄存器为其默认状态,即关PIE所有中断及清除所有标志。
// 这个函数由DSP281x_PieCtrl.c文件建立。
InitPieCtrl();
// 关CPU中断并清CPU所有中断标志:
IER = 0x0000;
IFR = 0x0000;
// 初始化PIE向量表,该向量表指明了中断服务程序(ISR)的一种构架(壳)。
// 即使在本例中没有用到中断,仍能板上组装整张表。这对于调试目的而言是很有用的。
// ISR壳程序由DSP281x_DefaultIsr.c文件建立。
InitPieVectTable(); // 这个函数由DSP281x_PieVect.c文件建立。
// 本例用到的中断重新映射到由本文件建立的ISR函数中。
//******************************************************************************************
// 关于 "PieVectTable.ADCINT = &adc_isr;" 指令的说明
// 1. adc_isr 是一个ADC模块中断服务程序(ISR)。
// 2. 这个中断程序与中断扩展(PIE)向量表第1组INT1第6个中断向量ADCINT(ADC)对应。 // 3. 为了使这个程序响应对应的中断,还需作如下配置:
// PieCtrlRegs.PIECRTL.bit.ENPIE = 1; // 使能PIE向量表。这条指令包含在上面调用的InitPieVectTable()函数中。 // IER |= M_INT1; // 使能PIE向量表第1组CPU INT1中断 // PieCtrlRegs.PIEIER1.bit.INTx6 = 1; // 使能PIE向量表第一组第6个ADCINT中断 // EINT; // 允许可屏蔽中断(清INTM位) // 这几条指令在本程序的后续指令中可以找到。这样,在发生ADCINT中断的情况下,将 // 执行adc_isr()中断服务程序。
// "PieVectTable.ADCINT = &adc_isr;" 指令实际上就是通知编译器,在发生ADCINT // 中断的情况下,将执行adc_isr()中断服务程序。adc_isr头上的"&"为取地址运算符。 //******************************************************************************************
EALLOW; // 允许访问受保护的寄存器
PieVectTable.ADCINT = &adc_isr;
EDIS; // 禁止访问受保护的寄存器
// 步骤4. 初始化器件所有外围设备:
//这个函数由DSP281x_InitPeripherals.c文件建立。
// InitPeripherals(); // 本例不需要
InitAdc(); // 初始化ADC模块
// 步骤5. 用户代码,中断使能:
PieCtrlRegs.PIEIER1.bit.INTx6 = 1; // 使能PIE向量表第一组第6个ADCINT中断
IER |= M_INT1; // 使能CPU 第一组中断
EINT; // 允许可屏蔽中断(清INTM位)
ERTM; // ERTM指令在外围设备头文件(DSP281x_Device.h)中有定义:
// #define ERTM asm(" clrc DBGM")。即清除DBGM位,作用为使能全局实时中断
LoopCount = 0; // 循环计数器初始化
ConversionCount = 0; // 转换计数器初始化
//******************************************************************************************
//关于输入通道选择序列控制寄存器注解:
// ADCCHSELSEQ1-ADCCHSELSEQ4 为4个16位ADC输入通道选择序列控制寄存器,从 // ADCCHSELSEQ1最低位开始,每一个4位值CONVnn(0<=nn<15)可以选择16个模拟输入通道(A通道或 // 是B通道)中的任何一路。每一个ADCCHSELSEQn(1<=n<=4)管理4个固定的CONVnn,其对应关系见下 // 面注释.输入通道选择个数必须与ADC最大转换通道(数)寄存器(ADCMAXCONV)的配置相匹配. // ADCCHSELSEQ1[3:0] =CONV00, ADCCHSELSEQ3[3:0] =CONV08, // ADCCHSELSEQ1[7:4] =CONV01, ADCCHSELSEQ3[7:4] =CONV09, // ADCCHSELSEQ1[11:8] =CONV02, ADCCHSELSEQ3[11:8] =CONV10, // ADCCHSELSEQ1[15:12]=CONV03, ADCCHSELSEQ3[15:12]=CONV11, // ADCCHSELSEQ2[3:0] =CONV04, ADCCHSELSEQ4[3:0] =CONV12, // ADCCHSELSEQ2[7:4] =CONV05, ADCCHSELSEQ4[7:4] =CONV13, // ADCCHSELSEQ2[11:8] =CONV06, ADCCHSELSEQ4[11:8] =CONV14, // ADCCHSELSEQ2[15:12]=CONV07, ADCCHSELSEQ4[15:12]=CONV15, //******************************************************************************************
AdcRegs.ADCMAXCONV.all = 0x000f; // 配置SEQ1模式16通道
AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x7; // 选择ADCINA0为SEQ模式第3通道
AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 0x7; // 选择ADCINA1为SEQ模式第3通道
AdcRegs.ADCCHSELSEQ1.bit.CONV02 = 0x7; // 选择ADCINA2为SEQ模式第3通道
AdcRegs.ADCCHSELSEQ1.bit.CONV03 = 0x7; // 选择ADCINA3为SEQ模式第3通道
AdcRegs.ADCCHSELSEQ2.bit.CONV04 = 0x7; // 选择ADCINA4为SEQ模式第3通道
AdcRegs.ADCCHSELSEQ2.bit.CONV05 = 0x7; // 选择ADCINA5为SEQ模式第3通道
AdcRegs.ADCCHSELSEQ2.bit.CONV06 = 0x7; // 选择ADCINA6为SEQ模式第3通道
AdcRegs.ADCCHSELSEQ2.bit.CONV07 = 0x7; // 选择ADCINA7为SEQ模式第3通道
AdcRegs.ADCCHSELSEQ3.bit.CONV08 = 0x7; // 选择ADCINB0为SEQ模式第3通道
AdcRegs.ADCCHSELSEQ3.bit.CONV09 = 0x7; // 选择ADCINB1为SEQ模式第3通道
AdcRegs.ADCCHSELSEQ3.bit.CONV10 = 0x7; // 选择ADCINB2为SEQ模式第3通道
AdcRegs.ADCCHSELSEQ3.bit.CONV11 = 0x7; // 选择ADCINB3为SEQ模式第3通道
AdcRegs.ADCCHSELSEQ4.bit.CONV12 = 0x7; // 选择ADCINB4为SEQ模式第3通道
AdcRegs.ADCCHSELSEQ4.bit.CONV13 = 0x7; // 选择ADCINB5为SEQ模式第3通道
AdcRegs.ADCCHSELSEQ4.bit.CONV14 = 0x7; // 选择ADCINB6为SEQ模式第3通道
AdcRegs.ADCCHSELSEQ4.bit.CONV15 = 0x7; // 选择ADCINB7为SEQ模式第3通道
AdcRegs.ADCTRL2.bit.EVA_SOC_SEQ1 = 1; // 使能EVASOC 启动SEQ1
AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 1; // 使能SEQ1 中断 (在每一个EOS时)
AdcRegs.ADCTRL3.bit.SMODE_SEL = 0; // 连续采样方式配置
// SMODE_SEL: 采样方式选择位。
// 当SMODE_SEL=0, 连续采样方式; 当SMODE_SEL=1, 并发采样方式。
// 所谓连续采样方式是指:一旦启动转换,则转换按照当前CONVxx决定的顺序
// 进行,xx 4位值的最高位确定是A引脚还是B引脚,低3位确定A引脚或B引脚
// 的偏移量,采样结果依次存入结果寄存器。在并发采样方式下,xx 最高位
// 被舍弃,系统根据低3位的偏移量先进行对应A引脚的采样再进行对应B引脚的
// 采样,采样结果也按照这一顺序存入结果寄存器。 (P352,P371)
AdcRegs.ADCTRL1.bit.SEQ_CASC = 1; // 级联方式配置
AdcRegs.ADCTRL2.bit.SOC_SEQ1 = 1;
// 启动SEQ1,触发模数转换。在级联方式琒EQ1管理16个通道?
// SEQ2被忽略
// 配置 EVA。假定EVA时钟已经在InitSysCtrl()函数中被使能。
EvaRegs.T1CMPR = 0x0080; // 设置 T1 比较值
EvaRegs.T1PR = 0xFFFF; // 设置周期寄存器 如何确定中断周期。
EvaRegs.GPTCONA.bit.T1TOADC = 1; // 使能EVA 的EVASOC
EvaRegs.T1CON.all = 0x1042; // 使能定时器1比较
// 等待ADC 中断
while(1)
{
LoopCount++;
if( Xram_pointer == 0x10 )
{
clearscr1(); // 第一显示缓冲区(0x0000-0x29ff)清零
VoltageCurve(); // 在液晶屏上制作电压曲线
AdcAverage(); // 求同一通道256个模数转换采样值的平均值
LedH_Display((Uint16 *)0x13f000);
LedD_Display((Uint16 *)0x13f000);
//delay(3); // 延时
}
}
}
//******************************************************************************************
// 函数名称: adc_isr(void)
// 函数功能: ADC模块中断服务函数
//******************************************************************************************
interrupt void adc_isr(void)
{
Xram_pointer++;
if (Xram_pointer<0x11) // 存16组模数转换
{
AdcResultCopy((Uint16 *) 0x7108, (Uint16 *)0x13eff0+16*Xram_pointer,16);
// 将每组16个模数转换值存入起始地址为0x13f000对应外存空间,共有16组256个数据。
// 第一次调用该程序时,Xram_pointer=1,故0x13eff0+16*Xram_pointer=0x13f000。
AdcRegs.ADCTRL2.bit.RST_SEQ1 = 1; // 复位SEQ1
AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1; // 清除INT SEQ1 bit
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; // 应答PIE 中断
}
else
{
Xram_pointer=0; // 初始化外存(存储组)跟踪指针
AdcRegs.ADCTRL2.bit.RST_SEQ1 = 1; // 复位SEQ1
AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1; // 清除INT SEQ1 bit
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; // 应答PIE 中断
}
}
/*
Voltage1[ConversionCount] = AdcRegs.ADCRESULT0 >>4;
//Voltage2[ConversionCount] = AdcRegs.ADCRESULT1 >>4;
if( ConversionCount == 256 ) // 如果已经记录了10个转换,则进行覆盖。
{
ConversionCount = 0;
}
else ConversionCount++;
// 重新初始化下一个ADC序列( 发生器 )
AdcRegs.ADCTRL2.bit.RST_SEQ1 = 1; // 复位SEQ1
AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1; // 清除INT SEQ1 bit
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; // 应答PIE 中断
return;
}
*/
/*******************************************************************************************
函数名称: VoltageCurve()
函数功能: 在液晶屏上制作电压曲线
*******************************************************************************************/
void VoltageCurve()
{
Uint16 i;
Uint16 x1,x2,y1,y2;
Xaddr=(Uint16 *)0x13f000;
for(i=0;i<250;i++)
{
x1=12+i;
x2=13+i;
//y1=(114+(int)(100))-(int)(((int)(*(Xaddr+i)/20.475)));
//y2=(114+(int)(100))-(int)(((int)(*(Xaddr+i+1)/20.475)));
y1=(114+(int)(100/2))-(int)(((int)(*(Xaddr+i)/20.475))/2);
y2=(114+(int)(100/2))-(int)(((int)(*(Xaddr+i+1)/20.475))/2);
if(y1!=y2) {liner(x1,y1,x1,y2,1);}
else { liner(x1,y1,x2,y2,1);}
//liner(x1,y1,x2,y2,1);
//dot(12+i,215-(int)(*Xaddr++/20.475),1);
}
}
/*******************************************************************************************
函数名称: delay(Uint16 dly)
函数功能: 延时函数
输入参数: 形参dly,dly越大延时越久
输出参数: 无
*******************************************************************************************/
void delay(Uint16 dly)
{
Uint16 i;
for(;dly>0;dly--)
{
for(i=0;i<60000;i++);
}
}
/*******************************************************************************************
函数名称: OscillographTable()
函数功能: 制作示波器表格
*******************************************************************************************/
void OscillographTable()
{
DashedLevel_n(14,1,250,2,9);
DashedLevel_n(15,1,250,2,1);
DashedLevel_n(16,1,250,2,1);
DashedLevel_n(113,1,250,2,1);
DashedLevel_n(115,1,250,2,1);
DashedLevel_n(213,1,250,2,1);
DashedLevel_n(215,1,250,2,1);
DashedVertical_n(12,14,195,2,11);
DashedVertical_n(13,14,195,2,1);
DashedVertical_n(14,14,195,2,1);
DashedVertical_n(136,14,195,2,1);
DashedVertical_n(138,14,195,2,1);
DashedVertical_n(260,14,195,2,1);
DashedVertical_n(261,14,195,2,1);
DrawaLevel(14,12,320,2);
DrawaLevel(215,12,320,2);
DrawaVertical(12,14,214,2);
DrawaVertical(262,14,214,2);
}
/*******************************************************************************************
函数名称: AdcAverage()
函数功能: 求同一通道256个模数转换采样值的平均值
*******************************************************************************************/
void AdcAverage()
{
Uint16 i;
Uint32 j=0;
Xaddr=(Uint16 *)0x13f000;
for(i=0;i<0x100;i++)
{
//j+=Voltage1[i];
j+=*Xaddr++;
}
Xaddr=(Uint16 *)0x13f000;
*Xaddr=j>>8;
}
/*******************************************************************************************
函数名称: AdcResultCopy()
函数功能: 这个函数的原型为MemCopy()函数,仅仅作了右移4位及起始地址跟踪的变异。其功能
为将内存起始地址(AdcResultAddr)开始的连续number个寄存器中的数据顺序拷贝到始
地址为AdcObjectXram的外存对应单元中。
输入参数: 第一形参AdcResultAddr为一个指针变量,指向Adc结果寄存器某一地址。实参固定为
0x7108,即模数转换结果首地址。
第二形参AdcObjectXram,为存入外存的起始地址。实际使用时为动态值,
由变量Avg_pointer确定偏移量,前后两者相差16,以便有序存入下一组16个模数转换
结果。
第三形参number为拷贝到外存的数据的个数。
输出参数: 无
*******************************************************************************************/
void AdcResultCopy(Uint16 *AdcResultAddr, Uint16 *AdcObjectXram,Uint16 number)
{
Uint16 i;
for(i=0;i>4;
// (*AdcResultAddr++)>>4的含义为: 取出某一个Adc
// 结果寄存器的数据右移4位后地址加1。
}
}
//================================================================================
// No more.
//================================================================================
二、
//******************************************************************************************
文件: Example_281xAdcSeq_ovdTest.c 标题: DSP281x ADC Seq Override mode Test. DSP281x ADC 序列发生器替换模式测试 说明: 这个程序需要V1.00头文件支持。另外,该项目需要配置成"boot to H0"操作方式。
在编译这个示例之前,确保CPU时钟与DSP281x_Examples.h定义的时钟相匹配。
将信号连接到通道A0进行转换
通道A0一直处于转换状态,其转换值记录到SampleTable缓冲器中。
在序列发生器替换模式中采用SEQ1(序列发生器1)。所谓序列(发生器)是一个在8.3MHz1/(3*40ns)
采样速率的连续模式。
打开内存窗口观察采样表(SampletTable)缓冲器,运行一下程序然后停止看一看表中的内容。 观察变量:
SampleTable - 记录变换值
XF - 在每一个ADC序列(发生器)之后触发
///******************************************************************************************
#include "DSP281x_Device.h" // DSP281x 头文件包含文件 #include "DSP281x_Examples.h" // DSP281x 示例包含文件
#include "math.h"
// 当模数转换数据产生时,确定右对齐移位。
// 以下3个只有一个定义为1,其它2个定义为0。
#define POST_SHIFT 1 // 在采样表存满后将结果移位。 #define INLINE_SHIFT 0 // 当数据从结果寄存器中取出时进行移位。 #define NO_SHIFT 0 // 不进行移位。
// ADC启动参数
#define ADC_MODCLK 0x3
// HSPCLK = SYSCLKOUT/2*ADC_MODCLK2 = 150/(2*3) = 25MHz
#define ADC_CKPS 0x0
// ADC模式时钟 = HSPCLK/1 = 25MHz/(1) = 25MHz #define ADC_SHCLK 0x1
// ADC周期模式中的S/H宽度 = 2 ADC cycle
#define AVG 1000 // Average sample limit平均采样限制 #define ZOFFSET 0x00 // Average Zero offset平均0漂移 #define BUF_SIZE 256 // Sample buffer size采样缓冲器大小
// Global variable for this example本例的全局变量
Uint16 SampleTable[BUF_SIZE];
void VoltageCurve();
void OscillographTable(); // 制作示波器表格
void AdcAverage();
void delay(Uint16 dly);
void liner();
Uint16 *Xaddr=(Uint16 *)0x13f000;
main()
{
Uint16 i;
Uint16 array_index;
// 步骤1. 系统控制初始化: PLL, WatchDog, 使能外设时钟。
// 这个示例函数在DSP281x_SysCtrl.c文件中建立
InitSysCtrl();
lcd_init();
clearscr1(); // 第一显示缓冲区(0x0000-0x29ff)清零
clearscr2(); // 第二显示缓冲区(0x2a00-0x53ff)清零
clearscr3(); // 第三显示缓冲区(0x5400-0x7dff)清零
OscillographTable();
// 本例的特殊时钟设置:
EALLOW;
SysCtrlRegs.HISPCP.all = ADC_MODCLK; // HSPCLK = SYSCLKOUT/ADC_MODCLK
EDIS;
// 步骤2. 初始化GPIO。这个示例函数由DSP281x_Gpio.c文件建立,例举如何将GPIO设置成
// 其默认状态.
// InitGpio(); // 本例跳过这个函数
// 使能XF引脚输出
EALLOW;
GpioMuxRegs.GPFMUX.bit.XF_GPIOF14 = 1; //enable XF pin on GPOF14
EDIS;
// 步骤3. 清除所有中断及初始化PIE向量表:
DINT;
// 初始化PIE控制寄存器为其默认状态,即关PIE所有中断及清除所有标志。 InitPieCtrl(); // 这个函数由DSP281x_PieCtrl.c文件建立。
// 关CPU中断并清CPU所有中断标志:
IER = 0x0000;
IFR = 0x0000;
// 初始化PIE向量表,该向量表指明了中断服务程序(ISR)的一种构架(壳)。
// 即使在本例中没有用到中断,仍能板上组装整张表。这对于调试而言是很有用的。
// ISR壳程序由DSP281x_DefaultIsr.c文件建立。
InitPieVectTable(); // 这个函数由DSP281x_PieVect.c文件建立。
// 步骤4. 初始化器件所有外围设备:
//这个函数由DSP281x_InitPeripherals.c文件建立。
// InitPeripherals(); // 本例不需要
InitAdc(); // 初始化ADC
// 适于本例的特殊的ADC设置步骤
AdcRegs.ADCTRL1.bit.ACQ_PS = ADC_SHCLK;
// 序列(发生器)模式: 采样速率 = 1/[(2+ACQ_PS)*ADC clock in ns] = 1/(3*40ns) =8.3MHz
// 如果使能并发模式: 采样速率 = 1/[(3+ACQ_PS)*ADC clock in ns]
AdcRegs.ADCTRL3.bit.ADCCLKPS = ADC_CKPS;
AdcRegs.ADCTRL1.bit.SEQ_CASC = 1; // 1 级联模式
AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x0;
AdcRegs.ADCTRL1.bit.CONT_RUN = 1; // 设置连续运行
AdcRegs.ADCTRL1.bit.SEQ_OVRD = 1; // 使能序列发生器替换特性
AdcRegs.ADCCHSELSEQ1.all = 0x0; // 初始化所有ADC通道选择A0
AdcRegs.ADCCHSELSEQ2.all = 0x0;
AdcRegs.ADCCHSELSEQ3.all = 0x0;
AdcRegs.ADCCHSELSEQ4.all = 0x0;
AdcRegs.ADCMAXCONV.bit.MAX_CONV1 = 0x7; // 开始转换并将结果存储到8个结果寄存器中。
// 步骤5. 用户代码,中断使能:
for (i=0; i>4);
SampleTable[array_index++]= ( (AdcRegs.ADCRESULT1)>>4);
SampleTable[array_index++]= ( (AdcRegs.ADCRESULT2)>>4);
SampleTable[array_index++]= ( (AdcRegs.ADCRESULT3)>>4);
SampleTable[array_index++]= ( (AdcRegs.ADCRESULT4)>>4);
SampleTable[array_index++]= ( (AdcRegs.ADCRESULT5)>>4);
SampleTable[array_index++]= ( (AdcRegs.ADCRESULT6)>>4);
SampleTable[array_index++]= ( (AdcRegs.ADCRESULT7)>>4); #endif //-- INLINE_SHIFT
#if NO_SHIFT || POST_SHIFT
SampleTable[array_index++]= ( (AdcRegs.ADCRESULT0));
SampleTable[array_index++]= ( (AdcRegs.ADCRESULT1));
SampleTable[array_index++]= ( (AdcRegs.ADCRESULT2));
SampleTable[array_index++]= ( (AdcRegs.ADCRESULT3));
SampleTable[array_index++]= ( (AdcRegs.ADCRESULT4));
SampleTable[array_index++]= ( (AdcRegs.ADCRESULT5));
SampleTable[array_index++]= ( (AdcRegs.ADCRESULT6));
SampleTable[array_index++]= ( (AdcRegs.ADCRESULT7)); #endif //-- NO_SHIFT || POST_SHIFT
while (AdcRegs.ADCST.bit.INT_SEQ1== 0){}
asm(" clrc XF "); // 清除XF 用以监视操作
AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1;
#if INLINE_SHIFT
SampleTable[array_index++]= ( (AdcRegs.ADCRESULT8)>>4);
SampleTable[array_index++]= ( (AdcRegs.ADCRESULT9)>>4);
SampleTable[array_index++]= ( (AdcRegs.ADCRESULT10)>>4);
SampleTable[array_index++]= ( (AdcRegs.ADCRESULT11)>>4);
SampleTable[array_index++]= ( (AdcRegs.ADCRESULT12)>>4);
SampleTable[array_index++]= ( (AdcRegs.ADCRESULT13)>>4);
SampleTable[array_index++]= ( (AdcRegs.ADCRESULT14)>>4);
SampleTable[array_index++]= ( (AdcRegs.ADCRESULT15)>>4); #endif //-- INLINE_SHIFT
#if NO_SHIFT || POST_SHIFT
SampleTable[array_index++]= ( (AdcRegs.ADCRESULT8));
SampleTable[array_index++]= ( (AdcRegs.ADCRESULT9));
SampleTable[array_index++]= ( (AdcRegs.ADCRESULT10));
SampleTable[array_index++]= ( (AdcRegs.ADCRESULT11));
SampleTable[array_index++]= ( (AdcRegs.ADCRESULT12));
SampleTable[array_index++]= ( (AdcRegs.ADCRESULT13));
SampleTable[array_index++]= ( (AdcRegs.ADCRESULT14));
SampleTable[array_index++]= ( (AdcRegs.ADCRESULT15)); #endif // -- NO_SHIFT || POST_SHIFT
}
#if POST_SHIFT
// 对于收进移位(POST_SHIFT),就是在采样表(SampleTable)缓冲器
// 存满后将ADC结果移位
for (i=0; i>4);
}
clearscr1(); // 第一显示缓冲区(0x0000-0x29ff)清零
VoltageCurve();
AdcAverage();
LedH_Display((Uint16 *)0x13f000);
LedD_Display((Uint16 *)0x13f000);
delay(10); // 延时
#endif // -- POST_SHIFT
asm(" clrc XF ");
}
}
void VoltageCurve()
{
Uint16 i;
Uint16 x1,x2,y1,y2;
Xaddr=(Uint16 *)0x13f000;
for(i=0;i<250;i++)
{
x1=12+i;
x2=13+i;
y1=(114+(int)(100))-(int)( (int)(SampleTable[i]/20.475) );
y2=(114+(int)(100))-(int)( (int)(SampleTable[i+1]/20.475) );
if(y1!=y2) {liner(x1,y1,x1,y2,1);}
else { liner(x1,y1,x2,y2,1);}
//liner(x1,y1,x2,y2,1);
//######################################################## // Uint16 i;
// for(i=0;i<250;i++)
// {
// dot(12+i,215-(int)(SampleTable[i]/20.475),1); // }
//########################################################
}
}
/*******************************************************************************************
函数名称: delay(Uint16 dly)
函数功能: 延时函数
输入参数: 形参dly,dly越大延时越久
输出参数: 无
*******************************************************************************************/
void delay(Uint16 dly)
{
Uint16 i;
for(;dly>0;dly--)
{
for(i=0;i<60000;i++);
}
}
/*******************************************************************************************
函数名称: OscillographTable()
函数功能: 制作示波器表格
*******************************************************************************************/
void OscillographTable()
{
DashedLevel_n(14,1,250,2,9);
DashedLevel_n(15,1,250,2,1);
DashedLevel_n(16,1,250,2,1);
DashedLevel_n(113,1,250,2,1);
DashedLevel_n(115,1,250,2,1);
DashedLevel_n(213,1,250,2,1);
DashedLevel_n(215,1,250,2,1);
DashedVertical_n(12,14,195,2,11);
DashedVertical_n(13,14,195,2,1);
DashedVertical_n(14,14,195,2,1);
DashedVertical_n(136,14,195,2,1);
DashedVertical_n(138,14,195,2,1);
DashedVertical_n(260,14,195,2,1);
DashedVertical_n(261,14,195,2,1);
DrawaLevel(14,12,320,2);
DrawaLevel(215,12,320,2);
DrawaVertical(12,14,214,2);
DrawaVertical(262,14,214,2);
}
/*******************************************************************************************
函数名称: AdcAverage()
函数功能: 制作示波器表格
*******************************************************************************************/
void AdcAverage()
{
Uint16 i;
Uint32 j=0;
for(i=0;i<0x100;i++)
{
j+=SampleTable[i];
}
*Xaddr=j>>8;
}
//================================================================================
// No more.
//================================================================================
三、序列发生器模式测试
文件: Example_281xAdcSeqModeTest.c 标题: DSP281x ADC Seq Mode Test. DSP281x ADC 序列发生器模式测试 说明: 这个程序需要V1.00头文件支持。另外,该项目需要配置成"boot to H0"操作方式。
在编译这个示例之前,确保CPU时钟与DSP281x_Examples.h定义的时钟相匹配。
将信号连接到通道A0进行转换
通道A0一直处于转换状态,其转换值记录到SampleTable缓冲器中。
打开内存窗口观察采样表(SampletTable)缓冲器,运行一下程序然后停止观察表中的内容。 观察变量:
SampleTable -记录变换值.
//******************************************************************************************
#include "DSP281x_Device.h" // DSP281x 头文件包含文件
#include "DSP281x_Examples.h" // DSP281x 示例包含文件
// ADC start parameters
#define ADC_MODCLK 0x3 // HSPCLK = SYSCLKOUT/2*ADC_MODCLK2 = 150/(2*3) = 25MHz
#define ADC_CKPS 0x1 // ADC模式时钟= HSPCLK/2*ADC_CKPS = 25MHz/(1*2) = 12.5MHz
#define ADC_SHCLK 0xf // ADC周期模式S/H宽度 = 16 ADC clocks #define AVG 256 // 平均采样限制
#define ZOFFSET 0x00 // 平均0漂移
#define BUF_SIZE 2048 // 采样缓冲器大小
// 本例的全局变量
Uint16 SampleTable[BUF_SIZE];
void OscillographTable(); // 制作示波器表格
void VoltageCurve();
void AdcAverage();
void delay(Uint16 dly);
void liner();
Uint16 *Xaddr=(Uint16 *)0x13f000; main()
{
Uint16 i;
// 步骤1. 系统控制初始化: PLL, WatchDog, 使能外设时钟。
// 这个示例函数在DSP281x_SysCtrl.c文件中建立.
InitSysCtrl();
lcd_init();
clearscr1(); // 第一显示缓冲区(0x0000-0x29ff)清零
clearscr2(); // 第二显示缓冲区(0x2a00-0x53ff)清零
clearscr3(); // 第三显示缓冲区(0x5400-0x7dff)清零
OscillographTable();
// 本例的特殊时钟设置:
EALLOW;
SysCtrlRegs.HISPCP.all = ADC_MODCLK; // HSPCLK = SYSCLKOUT/ADC_MODCLK
EDIS;
// 步骤2. 初始化GPIO。这个示例函数由DSP281x_Gpio.c文件建立,例举如何将GPIO设置成
// 其默认状态.
//InitGpio(); // 本例跳过这个函数
// 步骤3. 清除所有中断及初始化PIE向量表:
// Disable CPU interrupts
DINT;
// 初始化PIE控制寄存器为其默认状态,即关PIE所有中断及清除所有标志。
// 这个函数由DSP281x_PieCtrl.c文件建立。
InitPieCtrl();
// 关CPU中断并清CPU所有中断标志:
IER = 0x0000;
IFR = 0x0000;
// 初始化PIE向量表,该向量表指明了中断服务程序(ISR)的一种构架(壳)。
// 即使在本例中没有用到中断,仍能板上组装整张表。这对于调试而言是很有用的。
// ISR壳程序由DSP281x_DefaultIsr.c文件建立。
InitPieVectTable(); // 这个函数由DSP281x_PieVect.c文件建立。
// 步骤4. 初始化器件所有外围设备:
// 这个函数由DSP281x_InitPeripherals.c文件建立。
//InitPeripherals(); // 本例不需要
InitAdc(); // 初始化ADC
// Specific ADC setup for this example:
AdcRegs.ADCTRL1.bit.ACQ_PS = ADC_SHCLK;
AdcRegs.ADCTRL3.bit.ADCCLKPS = ADC_CKPS;
AdcRegs.ADCTRL1.bit.SEQ_CASC = 1; // SEQ_CASC =1, 级联模式
AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x0; // 选择A0通道
AdcRegs.ADCTRL1.bit.CONT_RUN = 1; // 设置连续运行
// 步骤5. 用户代码,中断使能:
for (i=0; i>4) );
}
clearscr1(); // 第一显示缓冲区(0x0000-0x29ff)清零
VoltageCurve();
AdcAverage();
LedH_Display((Uint16 *)0x13f000);
LedD_Display((Uint16 *)0x13f000);
delay(10); // 延时
}
}
/*******************************************************************************************
函数名称: VoltageCurve()
函数功能:
*******************************************************************************************/
void VoltageCurve()
{
Uint16 i;
Uint16 x1,x2,y1,y2;
Xaddr=(Uint16 *)0x13f000;
for(i=0;i<250;i++)
{
x1=12+i;
x2=13+i;
y1=(114+(int)(100))-(int)( (int)(SampleTable[i]/20.475) );
y2=(114+(int)(100))-(int)( (int)(SampleTable[i+1]/20.475) );
if(y1!=y2) {liner(x1,y1,x1,y2,1);}
else { liner(x1,y1,x2,y2,1);}
//Uint16 i;
//for(i=0;i<250;i++)
//{
// dot(12+i,215-(int)(SampleTable[i]/20.475),1);
}
}
/*******************************************************************************************
函数名称: delay(Uint16 dly)
函数功能: 延时函数
输入参数: 形参dly,dly越大延时越久
输出参数: 无
*******************************************************************************************/
void delay(Uint16 dly)
{
Uint16 i;
for(;dly>0;dly--)
{
for(i=0;i<60000;i++);
}
}
/*******************************************************************************************
函数名称: OscillographTable()
函数功能: 制作示波器表格
*******************************************************************************************/
void OscillographTable()
{
DashedLevel_n(14,1,250,2,9);
DashedLevel_n(15,1,250,2,1);
DashedLevel_n(16,1,250,2,1);
DashedLevel_n(113,1,250,2,1);
DashedLevel_n(115,1,250,2,1);
DashedLevel_n(213,1,250,2,1);
DashedLevel_n(215,1,250,2,1);
DashedVertical_n(12,14,195,2,11);
DashedVertical_n(13,14,195,2,1);
DashedVertical_n(14,14,195,2,1);
DashedVertical_n(136,14,195,2,1);
DashedVertical_n(138,14,195,2,1);
DashedVertical_n(260,14,195,2,1);
DashedVertical_n(261,14,195,2,1);
DrawaLevel(14,12,320,2);
DrawaLevel(215,12,320,2);
DrawaVertical(12,14,214,2);
DrawaVertical(262,14,214,2);
}
/*******************************************************************************************
函数名称: AdcAverage()
函数功能: 求平均值
*******************************************************************************************/
void AdcAverage()
{
Uint16 i;
Uint32 j=0;
for(i=0;i<0x100;i++)
{
j+=SampleTable[i];
}
*Xaddr=j>>8;
}
//================================================================================
// No more.
//================================================================================
四、模数转换,数模转换以及产生PWM综合程序 文件: AdcDacEvPwm.c
标题: 模数转换,数模转换以及通过事件管理产生PWM综合程序
条件: 本程序需要DSP281x V1.00头文件支持,另外需配置成"boot to H0"操作方式。
除了boot方式引脚配置外,无需其他硬件配置方式。
说明: (1) 本例采用中断方式对模数转换进行采样。所有16个CONVnn(00?nn?15)均选择ADCINA7
同一个输入通道。旋动最下方电位器的旋钮,改变ADCINA7输入通道的采样值,液晶屏上将显示电
压波形曲线的变化。
(2) 该程序设置EV定时器(TIMER1, TIMER2, TIMER3 and TIMER4),用于产生T1PWM, T2PWM,
T3PWM, T4PWM and PWM1-PWM12波形。将相应的端口接入ADCINA7,可通过液晶屏观察这些波
形。
(3) 数模转换采用TLV5614芯片,通过SPI同步串行传送数据及选择输出端口,将数模转换的有
效端口接入ADCINA7,可通过液晶屏观察电压波形随传送数据的变化而变化。
(4) 右边4个LED数码管以10进制、左边4个LED数码管以16进制显示EvPwm发生的次数。
TLV5614简介:
友情提醒:请参照大板原理图看下面一段文字。
(1) 引脚功能
TLV5614与DSP2812通过4根线连接。其中3根用于SPI通信,对应连接为:
DIN <- SPISIMOA(GPIOF0), SCLK <- SPICLKA(GPIOF2), FS <- SPISTEA(GPIOF3).
TLV5614的DIN引脚接收来自DSP的串行数字输入,SCLK为串行时钟输入引脚,FS为帧同步
输入引脚。另一根线用于控制输出更新。其连接为:LDAC <- SCIRXDB(GPIOG5).当 LDAC 为高电
平时,DAC输出不进行更新;只有当LDAC 为低电平时,DAC输出才进行更新。
(2) 数据格式
TLV5614接收的16位数字输入包含两个部分:
第一部分:控制位(D15,D14,D13,D12)
第二部分:新DAC值(D12,D11,...,D1,D0)
____________________________________________________________
| D15| D14| D13| D12| D11| D10| D9| D8| D7| D6| D5| D4| D3| D2| D1| D0|
|____|____|____|____|____|____|___|___|___|___|___|___|___|___|___|___|
| A1 | A0| PWR| SPD| 新DAC值(12位) |
|____|____|____|____|__________________________________________|
SPD: 速度控制位 SPD=1,快模式; SPD=0,慢模式。
PWR:电源控制位 PWR=1,掉电; PWR=0,正常操作。
在掉电状态下,关闭TLV5614内部所有放大器。
通过输入字的A1,A0位可对DAC的A,B,C,D 4个输出通道进行选择。
A1 A0 DAC输出
0 0 OUTA
0 1 OUTB
1 0 OUTC
1 1 OUTD
*******************************************************************************************/
#include "DSP281x_Device.h" // DSP281x 头文件包含文件
#include "DSP281x_Examples.h" // DSP281x 示例包含文件
// 本文件建立的函数原型声明。
void init_eva(void); // EVA配置T1PWM, T2PWM, PWM1-PWM6 ,初始化定时器
void init_evb(void); // EVB配置T1PWM, T2PWM, PWM1-PWM6 ,初始化定时器
void delay(); // 延时函数
//######################################################################### void spi_fifo_init(void);
interrupt void spiTxFifoIsr(void);
//######################################################################### interrupt void adc_isr(void);
//Uint16 SampleTable[BUF_SIZE];
void OscillographTable(); // 制作示波器表格
//void AdcAverage();
void VoltageCurve();
void AdcResultCopy();
//void delay(Uint16 dly);
Uint16 *Xaddr=(Uint16 *)0x13f000; Uint16 Xram_pointer=0;
//#define BUF_SIZE 256 // 采样缓冲器大小
// 本例的全局变量
//Uint16 SampleTable[BUF_SIZE];
// 外部函数声明。由Bc7281.c 文件建立
void LedD_Display(void);
// 将模数转换值以10进制形式,在Led第4,3,2,1位数码管上进行显示 void LedH_Display(void);
// 将模数转换值以16进制两个字节形式,在Led第8,7,6,5位数码管上进行显示
// 本例中的全局计数器
int count=0,i;
Uint16 temp=0;
Uint16 UpDown=0;
void main(void)
{
// 步骤1 系统控制初始化: 锁相环(PLL),看门狗(WatchDog)及外设时钟
// (PeripheralClocks)初始化。该函数在DSP281x_SysCtrl.c文件中建立。
InitSysCtrl();
// 步骤2.初始化GPIO:
// 这个函数例举怎样将GPIO设置成其默认状态,该函数由DSP281x_Gpio.c文件建立。
//InitGpio(); // 本例跳过这个函数
lcd_init();
clearscr1(); // 第一显示缓冲区(0x0000-0x29ff)清零
clearscr2(); // 第二显示缓冲区(0x2a00-0x53ff)清零
clearscr3(); // 第三显示缓冲区(0x5400-0x7dff)清零
OscillographTable();
// 对于这个检测仅初始化GPAMUX和GPBMUX
EALLOW; //允许访问受保护的空间
GpioMuxRegs.GPAMUX.all = 0x00FF; // 使能EVA PWM 1-6 脚
GpioMuxRegs.GPBMUX.all = 0x00FF; // 使能EVB PWM 7-12 脚
EDIS; //禁止访问受保护的空间
EALLOW; // 允许访问受保护的寄存器
GpioMuxRegs.GPAMUX.all=0x0000; // 将A端口设置成IO方式
GpioMuxRegs.GPADIR.all=0xffff; // 将GPIO A所有15个端口配置成数字量输出
EDIS; // 禁止访问受保护的寄存器
GpioDataRegs.GPADAT.all=0xAAAA; // 间隔一个点亮LED发光二极管。 //#########################################################################
EALLOW;
GpioMuxRegs.GPFMUX.all=0x000F; // 将GPIOF0-GPIOF3设置成SPI引脚。
GpioMuxRegs.GPGDIR.bit.GPIOG5=1; // 将GPIOG5引脚设置为输出。
EDIS;
//#########################################################################
// 步骤3 关所有中断并初始化PWM矢量表
DINT; // 关CPU中断
InitPieCtrl(); // 初始化PIE控制寄存器为默认状态。该状态关所有PIE中断并清除所有标识。该函
// 数在DSP281x_PieCtrl.c文件中建立。
IER = 0x0000; // 关CPU中断并清CPU中断标识。
IFR = 0x0000;
InitPieVectTable();
// 初始化PIE向量表,该向量表指出中断服务程序(ISR)的构架。即使在本范例中
// 没有用到中断,仍旧组装整张表。它在程序调试时是很有用的。ISR程序构架由
// DSP281x_DefaultIsr.c文件建立
// InitPieVectTable()函数由DSP281x_PieVect.c文件建立
// SPI中断(备用)
//##########################################################################################
// EALLOW; // 允许访问受保护的寄存器。
// PieVectTable.SPITXINTA = &spiTxFifoIsr; // EDIS; // 禁止访问受保护的寄存器。
// GpioDataRegs.GPFDAT.bit.GPIOF4=1; // GpioDataRegs.GPFDAT.bit.GPIOF5 =0; // PieCtrlRegs.PIECRTL.bit.ENPIE = 1; // 使能PIE 模块
// PieCtrlRegs.PIEIER6.bit.INTx2=1; // 使能PIE向量表第6组第2个SPITXINTA中断 // IER=0x20; // 使能CPU INT6 第6组中断
// EINT; // 使能全局中断
//##########################################################################################
// 本例用到的中断重新映射到由本文件建立的ISR函数中。
//******************************************************************************************
// 关于 "PieVectTable.ADCINT = &adc_isr;" 指令的说明
// 1. adc_isr 是一个ADC模块中断服务程序(ISR)。
// 2. 这个中断程序与中断扩展(PIE)向量表第1组INT1第6个中断向量ADCINT(ADC)对应。 // 3. 为了使这个程序响应对应的中断,还需作如下配置:
// PieCtrlRegs.PIECRTL.bit.ENPIE = 1; // 使能PIE向量表。这条指令包含在上面调用的InitPieVectTable()函数中。
// IER |= M_INT1; // 使能PIE向量表第1组CPU INT1中断 // PieCtrlRegs.PIEIER1.bit.INTx6 = 1; // 使能PIE向量表第一组第6个ADCINT中断 // EINT; // 使能全局中断(清INTM位) // 这几条指令在本程序的后续指令中可以找到。这样,在发生ADCINT中断的情况下,将执行adc_isr() // 中断服务程序。
// "PieVectTable.ADCINT = &adc_isr;" 指令实际上就是通知编译器,在发生ADCINT中断的情况下,将 // 执行adc_isr()中断服务程序。adc_isr头上的"&"为取地址运算符。
//******************************************************************************************
EALLOW; // 允许访问受保护的寄存器
PieVectTable.ADCINT = &adc_isr;
EDIS; // 禁止访问受保护的寄存器
// 步骤4. 初始化器件所有外围设备:
// 这个函数由DSP281x_InitPeripherals.c文件建立。
// InitPeripherals(); // 本例不需要
InitAdc(); // 初始化ADC模块
// Step 5. User specific code, enable interrupts:
// 步骤5. 用户代码,中断使能:
// 使能PIE模块ADCINT中断
PieCtrlRegs.PIEIER1.bit.INTx6 = 1; // 使能PIE向量表第一组第6个ADCINT中断
IER |= M_INT1; // 使能CPU 第一组中断
EINT; // 使能全局中断(清INTM位)
ERTM; // ERTM指令在外围设备头文件(DSP281x_Device.h)中有定义:
// #define ERTM asm(" clrc DBGM")。即清除DBGM位,作用为使能全局实时中断
spi_fifo_init(); // 初始化SPI
//******************************************************************************************
//关于输入通道选择序列控制寄存器注解:
// ADCCHSELSEQ1-ADCCHSELSEQ4 为4个16位ADC输入通道选择序列控制寄存器,从 // ADCCHSELSEQ1最低位开始,每一个4位值CONVnn(0<=nn<15)可以选择16个模拟输入通道(A通道或 // 是B通道)中的任何一路。每一个ADCCHSELSEQn(1<=n<=4)管理4个固定的CONVnn,其对应关系见下// 面注释.
// 输入通道选择个数必须与ADC最大转换通道(数)寄存器(ADCMAXCONV)的配置相匹配. // ADCCHSELSEQ1[3:0] =CONV00, ADCCHSELSEQ3[3:0] =CONV08, // ADCCHSELSEQ1[7:4] =CONV01, ADCCHSELSEQ3[7:4] =CONV09, // ADCCHSELSEQ1[11:8] =CONV02, ADCCHSELSEQ3[11:8] =CONV10, // ADCCHSELSEQ1[15:12]=CONV03, ADCCHSELSEQ3[15:12]=CONV11, // ADCCHSELSEQ2[3:0] =CONV04, ADCCHSELSEQ4[3:0] =CONV12, // ADCCHSELSEQ2[7:4] =CONV05, ADCCHSELSEQ4[7:4] =CONV13, // ADCCHSELSEQ2[11:8] =CONV06, ADCCHSELSEQ4[11:8] =CONV14, // ADCCHSELSEQ2[15:12]=CONV07, ADCCHSELSEQ4[15:12]=CONV15, //******************************************************************************************
AdcRegs.ADCMAXCONV.all = 0x000f; // 配置级联方式(SEQ)16通道
AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x7; // CONV00选择ADCINA7
AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 0x7; // CONV01选择ADCINA7
AdcRegs.ADCCHSELSEQ1.bit.CONV02 = 0x7; // CONV02选择ADCINA7
AdcRegs.ADCCHSELSEQ1.bit.CONV03 = 0x7; // CONV03选择ADCINA7
AdcRegs.ADCCHSELSEQ2.bit.CONV04 = 0x7; // CONV04选择ADCINA7
AdcRegs.ADCCHSELSEQ2.bit.CONV05 = 0x7; // CONV05选择ADCINA7
AdcRegs.ADCCHSELSEQ2.bit.CONV06 = 0x7; // CONV06选择ADCINA7
AdcRegs.ADCCHSELSEQ2.bit.CONV07 = 0x7; // CONV07选择ADCINA7
AdcRegs.ADCCHSELSEQ3.bit.CONV08 = 0x7; // CONV08选择ADCINA7
AdcRegs.ADCCHSELSEQ3.bit.CONV09 = 0x7; // CONV09选择ADCINA7
AdcRegs.ADCCHSELSEQ3.bit.CONV10 = 0x7; // CONV10选择ADCINA7
AdcRegs.ADCCHSELSEQ3.bit.CONV11 = 0x7; // CONV11选择ADCINA7
AdcRegs.ADCCHSELSEQ4.bit.CONV12 = 0x7; // CONV12选择ADCINA7
AdcRegs.ADCCHSELSEQ4.bit.CONV13 = 0x7; // CONV13选择ADCINA7
AdcRegs.ADCCHSELSEQ4.bit.CONV14 = 0x7; // CONV14选择ADCINA7
AdcRegs.ADCCHSELSEQ4.bit.CONV15 = 0x7; // CONV15选择ADCINA7
AdcRegs.ADCTRL2.bit.EVA_SOC_SEQ1 = 1; // 使能EVASOC 启动SEQ1
AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 1; // 使能SEQ1 中断 (在每一个EOS时)
AdcRegs.ADCTRL3.bit.SMODE_SEL = 0; // 连续采样方式配置
// SMODE_SEL: 采样方式选择位。
// 当SMODE_SEL=0, 连续采样方式; 当SMODE_SEL=1, 并发采样方式。
// 所谓连续采样方式是指:一旦启动转换,则转换按照当前CONVxx决定的顺序
// 进行,xx 4位值的最高位确定是A引脚还是B引脚,低3位确定A引脚或B引脚
// 的偏移量,采样结果依次存入结果寄存器。在并发采样方式下,xx 最高位
// 被舍弃,系统根据低3位的偏移量先进行对应A引脚的采样再进行对应B引脚?
// 采样,采样结果也按照这一顺序存入结果寄存器。 (P352,P371)
AdcRegs.ADCTRL1.bit.SEQ_CASC = 1; // 级联方式配置
AdcRegs.ADCTRL2.bit.SOC_SEQ1 = 1;
// 启动SEQ1,触发模数转换。在级联方式下,SEQ1管理16个通道?SEQ2被忽略
// 配置 EVA。假定EVA时钟已经在InitSysCtrl()函数中被使能。
EvaRegs.T1CMPR = 0x0080; // 设置 T1 比较值
EvaRegs.T1PR = 0xFFFF; // 设置周期寄存器 如何确定中断周期。
EvaRegs.GPTCONA.bit.T1TOADC = 1; // 使能EVA 的EVASOC
EvaRegs.T1CON.all = 0x1042; // 使能定时器1比较
// 步骤4 初始化器件外设: 这个函数由DSP281x_InitPeripherals.c文件建立。 //InitPeripherals(); // 本例不需要这个函数
init_eva();
init_evb();
// 步骤5. 用户代码,中断使能:
// 无限循环. 可用示波器观察PWM引脚的波形。
for(;;)
{
if(count>9999) count=0;
count++;
clearscr1(); // 第一显示缓冲区(0x0000-0x29ff)清零
VoltageCurve(); // 在液晶屏上制作电压曲线
LedD_Display(); // 以十进制形式在右边4个数码管上显示count
LedH_Display(); // 以十六进制形式在在左边4个数码管上显示count // 不使用SPI中断
//#########################################################
if(temp>0x0980) {UpDown=1;}
else if(temp<0x10) {UpDown=0;}
if(UpDown==0) {temp+=0x10; }
else {temp-=0x10; }
SpiaRegs.SPITXBUF=0xD000+temp; // 通过SPISIMOA引脚发送数据。
// 0xD000用意为选择OUTD输出通道,快模式。
GpioDataRegs.GPGCLEAR.bit.GPIOG5=1; // 更新输出数据
GpioDataRegs.GPGSET.bit.GPIOG5=1; // 保持输出数据
//#########################################################
delay(1);
}
}
/*******************************************************************************************
函数名称: init_eva()
函数功能: EVA配置T1PWM, T2PWM, PWM1-PWM6 ,初始化定时器
*******************************************************************************************/
void init_eva()
{
//##################################################################
// EvbRegs.T3PR = 0xFFFF; // 定时器3周期设置 (P313) // EvbRegs.T3CMPR = 0x3C00; // 定时器3比较器设置
// EvbRegs.T3CNT = 0x0000; // 定时器3计数器设置
// EvbRegs.T3CON.all = 0x1042;
//##################################################################
// 初始化EVA定时器1
EvaRegs.T1PR = 0xFFFF; // 定时器1周期设置 (P313)
EvaRegs.T1CMPR = 0x3C00; // 定时器1比较器设置 (P313)
EvaRegs.T1CNT = 0x0000; // T定时器1计数器设置 (P313)
EvaRegs.T1CON.all =0x1042;
// T1CON[15]=Free=0,与Soft合用。一旦仿真挂起,立即停止。 (P314)
// T1CON[14]=Soft=0,
// T1CON[13]=Reserved,保留
// T1CON[12:11]=TMODE1=10 B,连续递增模式。,
// T1CON[10:8]=TPS2-0=000 B,不分频,输入时钟频率同CPU时钟频率。
// T1CON[7]=T2SWT1/T4SWT3=0,T2SWT1对应EVA,使用定时器2的使能位启动定时器1,
// T4SWT1对应EVB,使用定时器4的使能位启动定时器3。
// 使用自身的使能位。
// T1CON[6]=TENABLE=1, 定时器使能。
// T1CON[5:4]=TCLK1-0=00 B,采用内部高速外设时钟(HSPCLK)
// T1CON[3:2]=TCLD1-0=00 B,当计数器为0时,定时器比较寄存器重载。
// T1CON[1]=TECMPR=1,定时器比较使能
// T1CON[0]=SELT1PR/SELT3PR=0,选用自身周期寄存器。
//######################################################################
// EvbRegs.T4PR = 0x00FF; // 定时器4周期设置 (P313) // EvbRegs.T4CMPR = 0x0030; // 定时器4比较器设置 (P313) // EvbRegs.T4CNT = 0x0000; // 定时器4计数器设置 (P313) // EvbRegs.T4CON.all = 0x1042;
//######################################################################
// 初始化EVA定时器2
EvaRegs.T2PR = 0x0FFF; // 定时器2周期设置 (P313)
EvaRegs.T2CMPR = 0x03C0; // 定时器2比较器设置 (P313)
EvaRegs.T2CNT = 0x0000; // 定时器2计数器设置 (P313)
EvaRegs.T2CON.all = 0x1042;
// T2CON[15]=Free=0,与Soft合用。一旦仿真挂起,立即停止。 (P314)
// T2CON[14]=Soft=0,
// T2CON[13]=Reserved,保留
// T2CON[12:11]=TMODE1=10 B,连续递增模式。,
// T2CON[10:8]=TPS2-0=000 B,不分频,输入时钟频率同CPU时钟频率。
// T2CON[7]=T2SWT1/T2SWT3=0,T2SWT1对应EVA,使用定时器2的使能位启动定时器1,
// T3SWT1对应EVB,使用定时器4的使能位启动定时器3。
// 使用自身的使能位。
// T2CON[6]=TENABLE=1, 定时器使能。
// T2CON[5:4]=TCLK1-0=00 B,采用内部高速外设时钟(HSPCLK)
// T2CON[3:2]=TCLD1-0=00 B,当计数器为0时,定时器比较寄存器重载。
// T2CON[1]=TECMPR=1,定时器比较使能
// T2CON[0]=SELT1PR/SELT3PR=0,选用自身周期寄存器。
//############################################################################
// EvbRegs.GPTCONB.bit.TCMPOE = 1; // // GTPCONB[6]=TCMPOE=1,通过比较逻辑驱动T3/T4 PWM (P318) // EvbRegs.GPTCONB.bit.T3PIN = 1; // // GPTCONB[1:0]=T3PIN = 01,GP定时器3比较器输出极性低电平有效。 // EvbRegs.GPTCONB.bit.T4PIN = 2; // // GPTCONB[3:2]=T4PIN = 10,GP定时器4比较器输出极性高电平有效。 //
// // 使能PWM7-PWM12的比较功能
// EvbRegs.CMPR4 = 0x0C00;
// EvbRegs.CMPR5 = 0x3C00;
// EvbRegs.CMPR6 = 0xFC00;
//############################################################################
// 设置T1PWM及T2PWM
EvaRegs.GPTCONA.bit.TCMPOE = 1;
// GTPCONA[6]=TCMPOE=1,通过比较逻辑驱动T1/T2 PWM (P315)
EvaRegs.GPTCONA.bit.T1PIN = 1;
// GPTCONA[1:0]=T1PIN = 01 B,GP定时器1比较器输出极性低电平有效。
EvaRegs.GPTCONA.bit.T2PIN = 2;
// GPTCONA[3:2]=T2PIN = 10 B,GP定时器2比较器输出极性高电平有效。
// 使能PWM1-PWM6的比较功能
// 原版找不到CMPRx的定义!
EvaRegs.CMPR1 = 0x0C00;
EvaRegs.CMPR2 = 0x3C00;
EvaRegs.CMPR3 = 0xFC00;
//########################################################################
// EvbRegs.ACTRB.all = 0x0666;
// output pin 1 CMPR4 - active high 输出引脚1(CMPR4)-高电平有效 (P325)
// output pin 2 CMPR4 - active low 输出引脚2(CMPR4)-低电平有效
// output pin 3 CMPR5 - active high 输出引脚3(CMPR5)-高电平有效
// output pin 4 CMPR5 - active low 输出引脚4(CMPR5)-低电平有效
// output pin 5 CMPR6 - active high 输出引脚5(CMPR6)-高电平有效
// output pin 6 CMPR6 - active low 输出引脚6(CMPR6)-低电平有效 // EvbRegs.DBTCONB.all = 0x0000; // Disable deadband 禁止死区 (P331) // EvbRegs.COMCONB.all = 0xA600;
//########################################################################
// Compare action control. Action that takes place 比较器方式控制。
// on a cmpare event 开事件比较器
EvaRegs.ACTRA.all = 0x0666;
// output pin 1 CMPR1 - active high 输出引脚1(CMPR1)-高电平有效 (P324)
// output pin 2 CMPR1 - active low 输出引脚2(CMPR1)-低电平有效
// output pin 3 CMPR2 - active high 输出引脚3(CMPR2)-高电平有效
// output pin 4 CMPR2 - active low 输出引脚4(CMPR2)-低电平有效
// output pin 5 CMPR3 - active high 输出引脚5(CMPR3)-高电平有效
// output pin 6 CMPR3 - active low 输出引脚6(CMPR3)-低电平有效
EvaRegs.DBTCONA.all = 0x0000; // Disable deadband 禁止死区 (P331)
EvaRegs.COMCONA.all = 0xA600;
// COMCONA[15]=CENABLE=1,使能比较操作。 (P319)
// COMCONA[14:13]=CLD1-0=01 B,当T1CNT=0 或T1CNT=T1PR (即下溢中断或周期匹配)
// COMCONA[12]=SVENABLE=0,禁止空间向量PWM模式。
// COMCONA[11:10]=ACTRLD1-0=01 B,当T1CNT=0或T1CNT=T1PR(即下溢或芷谄ヅ?时,
// 控制寄存器重载
// COMCONA[9]=FCMPOE=1,全比较输出使能,PWM1/2/3/4/5/6由相应比较逻辑驱动。
// COMCONA[8]=PDPINTA=0,该位反映PDPINTA引脚的状态。
// COMCONA[7]=PCMP3OE=0,全比较3输出,PWM5/6处于高阻。
// COMCONA[6]=PCMP2OE=0,全比较2输出,PWM3/4处于高阻。
// COMCONA[5]=PCMP1OE=0,全比较1输出,PWM1/2处于高阻。
// COMCONA[4:3]=Reserve
// COMCONA[2]=C3TRIPE=0,禁止C3TRIP。C3TRIP不影响比较输出3、COMCONA[8]或
// PDPINT标志位(EVAIFRA[0])。
// COMCONA[1]=C2TRIPE=0,禁止C2TRIP。C2TRIP不影响比较输出2、COMCONA[7]或
// PDPINT标志位(EVAIFRA[0])。
// COMCONA[0]=C1TRIPE=0, 禁止C1TRIP。C1TRIP不影响比较输出1、COMCONA[6]或
// PDPINT标志位(EVAIFRA[0])。
}
/*******************************************************************************************
函数名称: init_evb()
函数功能: EVB配置T1PWM, T2PWM, PWM1-PWM6 ,初始化定时器
*******************************************************************************************/
void init_evb()
{
// 初始化EVB定时器3
// 定时器3控制T3PWM及PWM7-12
EvbRegs.T3PR = 0xFFFF; // 定时器3周期设置 (P313)
EvbRegs.T3CMPR = 0x3C00; // 定时器3比较器设置
EvbRegs.T3CNT = 0x0000; // 定时器3计数器设置
EvbRegs.T3CON.all = 0x1042;
// T3CON[15]=Free=0,与Soft合用。一旦仿真挂起,立即停止。 (P314)
// T3CON[14]=Soft=0,
// T3CON[13]=Reserved,保留
// T3CON[12:11]=TMODE1=10 B,连续递增模式。,
// T3CON[10:8]=TPS2-0=000 B,不分频,输入时钟频率同CPU时钟频率。
// T3CON[7]=T2SWT1/T4SWT3=0,T2SWT1对应EVA,使枚ㄊ逼?的使能位启动定时器1,
// T4SWT1对应EVB,使用定时器4的使能位启动定时器3。
// 使用自身的使能位。
// T3CON[6]=TENABLE=1, 定时器使能。
// T3CON[5:4]=TCLK1-0=00 B,采用内部高速外设时钟(HSPCLK)
// T3CON[3:2]=TCLD1-0=00 B,当计数器为0时,定时器比较寄存器重载。
// T3CON[1]=TECMPR=1,定时器比较使能
// T3CON[0]=SELT1PR/SELT3PR=0,选用自身周期寄存器。
// 初始化EVB定时器4
// 定时器4控制T4PWM
EvbRegs.T4PR = 0x00FF; // 定时器4周期设置 (P313)
EvbRegs.T4CMPR = 0x0030; // 定时器4比较器设置 (P313)
EvbRegs.T4CNT = 0x0000; // 定时器4计数器设置 (P313)
EvbRegs.T4CON.all = 0x1042;
// T4CON[15]=Free=0,与Soft合用。一旦仿真挂起,立即停止。
// T4CON[14]=Soft=0,
// T4CON[13]=Reserved,保留
// T4CON[12:11]=TMODE1=10 B,连续递增模式。,
// T4CON[10:8]=TPS2-0=000 B,不分频,输入时钟频率同CPU时钟频率。
// T4CON[7]=T2SWT1/T4SWT3=0,T2SWT1对应EVA,使用定时器2的使能位启动定时器1,
// T4SWT1对应EVB,使用定时器4的使能位启动定时器3。
// 使用自身的使能位。
// T4CON[6]=TENABLE=1, 定时器使能。
// T4CON[5:4]=TCLK1-0=00 B,采用内部高速外设时钟(HSPCLK)
// T4CON[3:2]=TCLD1-0=00 B,当计数器为0时,定时器比较寄存器重载。
// T4CON[1]=TECMPR=1,定时器比较使能
// T4CON[0]=SELT1PR/SELT3PR=0,选用自身周期寄存器。
// 设置T3PWM及T4PWM
// 通过比较逻辑驱动T3/T4 PWM
EvbRegs.GPTCONB.bit.TCMPOE = 1;
// GTPCONB[6]=TCMPOE=1,通过比较逻辑驱动T3/T4 PWM (P318)
EvbRegs.GPTCONB.bit.T3PIN = 1;
// GPTCONB[1:0]=T3PIN = 01,GP定时器3比较器输出极性低电平有效。
EvbRegs.GPTCONB.bit.T4PIN = 2;
// GPTCONB[3:2]=T4PIN = 10,GP定时器4比较器输出极性高电平有效。
// 使能PWM7-PWM12的比较功能
EvbRegs.CMPR4 = 0x0C00;
EvbRegs.CMPR5 = 0x3C00;
EvbRegs.CMPR6 = 0xFC00;
// Compare action control. Action that takes place
// 比较器方式控制
// on a cmpare event 开事件比较器
EvbRegs.ACTRB.all = 0x0666;
// output pin 1 CMPR4 - active high 输出引脚1(CMPR4)-高电平有效 (P325)
// output pin 2 CMPR4 - active low 输出引脚2(CMPR4)-低电平有效
// output pin 3 CMPR5 - active high 输出引脚3(CMPR5)-高电平有效
// output pin 4 CMPR5 - active low 输出引脚4(CMPR5)-低电平有效
// output pin 5 CMPR6 - active high 输出引脚5(CMPR6)-高电平有效
// output pin 6 CMPR6 - active low 输出引脚6(CMPR6)-低电平有效
EvbRegs.DBTCONB.all = 0x0000; // Disable deadband 禁止死区 (P331)
EvbRegs.COMCONB.all = 0xA600;
// COMCONB[15]=CENABLE=1,使能比较操作。 (P321)
// COMCONB[14:13]=CLD1-0=01 B,当T3CNT=0 或T3CNT=T3PR (即下溢中断或周期匹配)
// COMCONB[12]=SVENABLE=0,禁止空间向量PWM模式。
// COMCONB[11:10]=ACTRLD1-0=01 B,当T3CNT=0或T3CNT=T3PR(即下溢或周期匹配)时,
// 控制寄存器重载。
// COMCONB[9]=FCMPOE=1,全比较输出使能,PWM1/2/3/4/5/6由相应比较逻辑驱动。
// COMCONB[8]=PDPINTA=0,该位反映PDPINTA引脚的状态。
// COMCONB[7]=PCMP3OE=0,全比较3输出,PWM5/6处于高阻。
// COMCONB[6]=PCMP2OE=0,全比较2输出,PWM3/4处于高阻。
// COMCONB[5]=PCMP1OE=0,全比较1输出,PWM1/2处于高阻。
// COMCONB[4:3]=Reserve
// COMCONB[2]=C3TRIPE=0,禁止C3TRIP。C3TRIP不影响比较输出3、COMCONA[8]或
// PDPINT标志位(EVAIFRA[0])。
// COMCONB[1]=C2TRIPE=0,禁止C2TRIP。C2TRIP不影响比较输出2、COMCONA[7]或
// PDPINT标志位(EVAIFRA[0])。
// COMCONB[0]=C1TRIPE=0, 禁止C1TRIP。C1TRIP不影响比较输出1、COMCONA[6]或
// PDPINT标志位(EVAIFRA[0])。
}
/*******************************************************************************************
函数名称: delay(Uint16 dly)
函数功能: 延时函数
输入参数: 形参dly,dly越大延时越久
输出参数: 无
*******************************************************************************************/
void delay(Uint32 dly)
{
Uint32 i;
for(;dly>0;dly--)
for(i=0;i<500000;i++);
}
/*******************************************************************************************
函数名称: OscillographTable()
函数功能: 制作示波器表格
*******************************************************************************************/
void OscillographTable()
{
DashedLevel_n(14,1,250,2,9);
DashedLevel_n(15,1,250,2,1);
DashedLevel_n(16,1,250,2,1);
DashedLevel_n(113,1,250,2,1);
DashedLevel_n(115,1,250,2,1);
DashedLevel_n(213,1,250,2,1);
DashedLevel_n(215,1,250,2,1);
DashedVertical_n(12,14,195,2,11);
DashedVertical_n(13,14,195,2,1);
DashedVertical_n(14,14,195,2,1);
DashedVertical_n(136,14,195,2,1);
DashedVertical_n(138,14,195,2,1);
DashedVertical_n(260,14,195,2,1);
DashedVertical_n(261,14,195,2,1);
DrawaLevel(14,12,320,2);
DrawaLevel(215,12,320,2);
DrawaVertical(12,14,214,2);
DrawaVertical(262,14,214,2);
}
//******************************************************************************************
// 函数名称: adc_isr(void)
// 函数功能: ADC模块中断服务函数
//******************************************************************************************
interrupt void adc_isr(void)
{
Xram_pointer++;
if (Xram_pointer<0x11) // 存16组模数转换
{
AdcResultCopy((Uint16 *) 0x7108, (Uint16 *)0x13eff0+16*Xram_pointer,16);
// 将每组16个模数转换值存入起始地址为0x13f000对应外存空间,共有16组
// 256个数据。
// 第一次调用该程序时,Xram_pointer=1,故0x13eff0+16*Xram_pointer=0x13f000。
AdcRegs.ADCTRL2.bit.RST_SEQ1 = 1; // 复位SEQ1
AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1; // 清除INT SEQ1 bit
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; // 应答PIE 中断
}
else
{
Xram_pointer=0; // 初始化外存(存储组)跟踪指针
AdcRegs.ADCTRL2.bit.RST_SEQ1 = 1; // 复位SEQ1
AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1; // 清除INT SEQ1 bit
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; // 应答PIE 中断
}
}
/*******************************************************************************************
函数名称: VoltageCurve()
函数功能: 在液晶屏上制作电压曲线
*******************************************************************************************/
void VoltageCurve()
{
Uint16 i;
Uint16 x1,x2,y1,y2;
Xaddr=(Uint16 *)0x13f000;
for(i=0;i<250;i++)
{
x1=12+i;
x2=13+i;
// y1=(114+(int)(100/2))-(int)(((int)(*(Xaddr+i)/20.475))/2); // y2=(114+(int)(100/2))-(int)(((int)(*(Xaddr+i+1)/20.475))/2);
y1=(114+(int)(75))-(int)(((int)(*(Xaddr+i) *0.036630036)));
y2=(114+(int)(75))-(int)(((int)(*(Xaddr+i+1) *0.036630036)));
if(y1!=y2) {liner(x1,y1,x1,y2,1);}
else { liner(x1,y1,x2,y2,1);}
// dot(12+i,215-(int)(*Xaddr++/20.475),1);
// dot(12+i,(114+(int)(100/2))-(int)(((int)(*Xaddr++/20.475))/2),1); //328 2
}
}
/*******************************************************************************************
函数名称: AdcResultCopy()
函数功能: 这个函数的原型为MemCopy()函数,仅仅作了右移4位及起始地址跟踪的变异。其功能
为将内存起始地址(AdcResultAddr)开始的连续number个寄存器中的数据顺序拷贝到始
地址为AdcObjectXram的外存对应单元中。
输入参数: 第一形参AdcResultAddr为一个指针变量,指向Adc结果寄存器某一地址。实参固定为
0x7108,即模数转换结果首地址。
第二形参AdcObjectXram,为存入外存的起始地址。实际使用时为动态值,
由变量Avg_pointer确定偏移量,前后两者相差16,以便有序存入下一组16个模数转换
结果。
第三形参number为拷贝到外存的数据的个数。
输出参数: 无
*******************************************************************************************/
void AdcResultCopy(Uint16 *AdcResultAddr, Uint16 *AdcObjectXram,Uint16 number)
{
Uint16 i;
for(i=0;i>4;
// (*AdcResultAddr++)>>4的含义为: 取出某一个Adc
// 结果寄存器的数据右移4位后地址加1。
}
}
/*******************************************************************************************
函数名称: spi_fifo_init()
函数功能: 初始化SPI FIFO寄存器为DA方式.无中断
*******************************************************************************************/
void spi_fifo_init()
{
SpiaRegs.SPICCR.all=0x000F;
// SPICCR[7]=SPI SW RESET=0, 复位SPI。
// SPICCR[6]=CLOCK POLARITY=0, 上升沿输出数据。
// SPICCR[5]=Reserved, 保留。
// SPICCR[4]=SPILBK=0, 禁止SPI会送模式。
// SPICCR[3:0]=SPICHAR3-SPICHAR0=1111b, 16位字长。
SpiaRegs.SPICTL.all=0x0006;
// SPICTL[7:5]=Reserved, 保留。
// SPICTL[4]=OVERRUN INT ENA=0, 禁止中断
// SPICTL[3]=CLOCK PHASE=0, 普通时钟方案
// SPICTL[2]=MASTER/SLAVE=1, 主机方式
// SPICTL[1]=TALK=1, 使能发送
// SPICTL[0]=SPI INT ENA=0, 使中断无效
SpiaRegs.SPIBRR=0x0009; // Baud rate
// 系统外设时钟 SYSCLKOUT = (30*5)/2 = 754 MHz 参见6.4.2
// 低速外设时钟 LSPCLK = 75/4 = 18.75 MHz
// SPI波特率 = LSPCLK/(SPIBRR+1)=18.75/10=1.875MHz
SpiaRegs.SPIPRI.all=0x0010;
// 忽视中断挂起,SPI继续工作。
SpiaRegs.SPICCR.bit.SPISWRESET=1; // Enable SPI
// SPI准备发送或接收下一字。
}
/*******************************************************************************************
函数名称: spi_fifo_init()
函数功能: 初始化SPI FIFO寄存器为DA方式.有中断
*******************************************************************************************/
/*
void spi_fifo_init()
{
// Initialize SPI FIFO registers for DA
SpiaRegs.SPICCR.bit.SPISWRESET=0; // Reset SPI
SpiaRegs.SPICCR.all=0x000F; //16-bit character, no Loopback mode
SpiaRegs.SPICTL.all=0x0017; //Interrupt enabled, Master/Slave XMIT enabled
SpiaRegs.SPISTS.all=0x0000;
SpiaRegs.SPIBRR=0x0063; // Baud rate
SpiaRegs.SPIFFTX.all=0xC028; // Enable FIFO's, set TX FIFO level to 8
SpiaRegs.SPIFFRX.all=0x0028; // Set RX FIFO level to 31
SpiaRegs.SPIFFCT.all=0x00;
SpiaRegs.SPIPRI.all=0x0010;
SpiaRegs.SPICCR.bit.SPISWRESET=1; // Enable SPI
SpiaRegs.SPIFFTX.bit.TXFIFO=1;
SpiaRegs.SPIFFRX.bit.RXFIFORESET=1;
}
*/
interrupt void spiTxFifoIsr(void)
{
SpiaRegs.SPITXBUF=0x4000+temp;//0x0800; // Send data //#########################################################
temp+=0x5;
if(temp==0x1000) {temp=0;}
GpioDataRegs.GPGCLEAR.bit.GPIOG5=1;
GpioDataRegs.GPGSET.bit.GPIOG5=1;
//#########################################################
SpiaRegs.SPIFFTX.bit.TXFFINTCLR=1; // Clear Interrupt flag
PieCtrlRegs.PIEACK.all|=0x20; // Issue PIE ACK
// delay(1);
}
//================================================================================
// No more.
//================================================================================