下面通过官方的一个外部中断例程讲解外部中断,所参考的文档为TMS320x2806x Piccolo Technical Reference Manual (Rev. H)
下面先通过该例程的代码进行学习探索,并且都有根据自己的理解添加了注释。
#include "DSP28x_Project.h"
volatile Uint32 Xint1Count;
volatile Uint32 Xint2Count;
Uint32 LoopCount;
#define DELAY (CPU_RATE/1000*6*510) //Qual period at 6 samples
void External_Interrupt_Init(void)
{
// Enable INT1 which is connected to WAKEINT:
PieCtrlRegs.PIECTRL.bit.ENPIE=1; //使能中断
PieCtrlRegs.PIEIER1.bit.INTx4=1; //使能INT1.4中断
PieCtrlRegs.PIEIER1.bit.INTx5=1; //使能INT1.4中断
IER|=M_INT1; //使能CPU中断
EINT;
EALLOW;
// GPIO32 & GPIO33 are outputs, start GPIO32 high and GPIO33 low
GpioDataRegs.GPBSET.bit.GPIO32=1; //初始化输出拉高
GpioCtrlRegs.GPBMUX1.bit.GPIO32=0; //设置为普通的IO
GpioCtrlRegs.GPBDIR.bit.GPIO32=1; //定义为输出
GpioDataRegs.GPBSET.bit.GPIO33=1; //初始化输出拉高
GpioCtrlRegs.GPBMUX1.bit.GPIO33=0; //设置为普通的IO
GpioCtrlRegs.GPBDIR.bit.GPIO33=1; //定义为输出
GpioDataRegs.GPBSET.bit.GPIO34=1; //初始化输出拉高
GpioCtrlRegs.GPBMUX1.bit.GPIO34 = 0; // GPIO
GpioCtrlRegs.GPBDIR.bit.GPIO34 = 1; // output
EDIS;
EALLOW;
// GPIO0 and GPIO1 are inputs
GpioCtrlRegs.GPAMUX1.bit.GPIO0=0; //设置普通的IO
GpioCtrlRegs.GPADIR.bit.GPIO0=0; //设置为输入
GpioCtrlRegs.GPAQSEL1.bit.GPIO0=0; //设置为与系统时钟同步
GpioCtrlRegs.GPAMUX1.bit.GPIO1=0; //设置普通的IO
GpioCtrlRegs.GPADIR.bit.GPIO1=0; //设置为输入
GpioCtrlRegs.GPAQSEL1.bit.GPIO1=2; //设置为6倍采样时间
GpioCtrlRegs.GPACTRL.bit.QUALPRD0=0xff;//每倍采样时间为510*SYSCLKOUT;
EDIS;
// GPIO0 is XINT1, GPIO1 is XINT2
EALLOW;
GpioIntRegs.GPIOXINT1SEL.bit.GPIOSEL=0; //定义GPIO为XINT1的来源
GpioIntRegs.GPIOXINT2SEL.bit.GPIOSEL=1; //定义GPIO1为XINT2的来源
EDIS;
// Configure XINT1 and XINT2
XIntruptRegs.XINT1CR.bit.POLARITY=0; //定义为下降沿触发
XIntruptRegs.XINT2CR.bit.POLARITY=1; //定义为上升沿触发
// Enable XINT1 and XINT2
XIntruptRegs.XINT1CR.bit.ENABLE=1; //使能XINT1
XIntruptRegs.XINT2CR.bit.ENABLE=1; //使能XINT2
}
void External_Control(void)
{
Uint32 TempX1Count=0;
Uint32 TempX2Count=0;
TempX1Count=Xint1Count;
TempX2Count=Xint2Count;
// Trigger both XINT1
GpioDataRegs.GPBSET.bit.GPIO34=1; //把GPIO拉高
GpioDataRegs.GPBCLEAR.bit.GPIO32=1; //拉低GPIO32,触发XINT1
while(Xint1Count==TempX1Count){}
// Trigger both XINT2
GpioDataRegs.GPBSET.bit.GPIO34=1; //把GPIO拉高
DELAY_US(DELAY);
GpioDataRegs.GPBSET.bit.GPIO33=1; //拉高GPIO33,触发XINT2
while(Xint2Count==TempX2Count){}
if(Xint1Count==TempX1Count+1&&Xint2Count==TempX2Count)
{
LoopCount++;
GpioDataRegs.GPBCLEAR.bit.GPIO33=1; //拉低GPIO33,停止触发XINT2
GpioDataRegs.GPBSET.bit.GPIO32=1; //拉高GPIO32,停止触发XINT1
}
else
{
__asm(" ESTOP0");//停止到这里
}
}
__interrupt void xint1_isr(void)
{
GpioDataRegs.GPBCLEAR.all=0x4; //GPIO34拉低
Xint1Count++;
// Acknowledge this interrupt to get more from group 1
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
}
__interrupt void xint2_isr(void)
{
GpioDataRegs.GPBCLEAR.all=0x4; //GPIO34拉低
Xint2Count++;
// Acknowledge this interrupt to get more from group 1
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
}
mian.c
void main(void)
{
InitSysCtrl(); //Step1
// GPIO_Init(); //step2
External_Interrupt_Init();
// step3;Disable CPU interrupts
DINT;
// Initialize the PIE control registers to their default state.
// The default state is all PIE interrupts disabled and flags
InitPieCtrl(); //中断初始化
// Disable CPU interrupts and clear all CPU interrupt flags:
IER = 0x0000;
IFR = 0x0000;
// Initialize the PIE vector table with pointers to the shell Interrupt
// Service Routines (ISR).
InitPieVectTable(); //中断向量表
// Interrupt that is used in this example is re-mapped to
// ISR function found within this file.
EALLOW;
// PieVectTable.EPWM1_INT=&epwm1_timer_isr; //把中断服务程序映射到中断向量表中
PieVectTable.XINT1=&xint1_isr;
PieVectTable.XINT2=&xint2_isr;
EDIS;
while(1)
{
External_Control();
}
}
根据文档可得,外部中断有96个独立的中断,分为了8个组,每个组分为12中断线。
下面进行具体的讲解:
主函数中:
step1:
InitSysCtrl();该函数是使能外设时钟
step2:
External_Interrupt_Init();该函数就是自己编写的外部中断初始化函数
step3:
DINT; 这里是失能CPU中断
step4:
InitPieCtrl();进行中断初始化
step5:
IER = 0x0000;
IFR = 0x0000; 先关闭中断,清除中断标志位
step6:
InitPieVectTable(); //初始化中断向量表
step7:
PieVectTable.XINT1=&xint1_isr;
PieVectTable.XINT2=&xint2_isr; 把中断服务程序映射到中断向量表中
void External_Interrupt_Init(void)
该函数首先以来就进行使能中断:
PieCtrlRegs.PIECTRL.bit.ENPIE=1; //使能中断
PieCtrlRegs.PIEIER1.bit.INTx4=1; //使能INT1.4中断INT1
PieCtrlRegs.PIEIER1.bit.INTx5=1; //使能INT1.5中断INT2
IER|=M_INT1; //使能CPU中断
EINT;

PIECTRL中的ENPIE设置为1,使能PIE.

PIEIER1使能中断。

PIEIER1,PIEIFR1,是INT1组的使能寄存器

根据这个表,看出XINT2,XINT1分别对应INTx.5,INTx.4
置1使能INT1
GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 0; // GPIO
GpioCtrlRegs.GPADIR.bit.GPIO0 = 0; // input
GpioCtrlRegs.GPAQSEL1.bit.GPIO0 = 0; // XINT1 Synch to SYSCLKOUT only
GpioCtrlRegs.GPAMUX1.bit.GPIO1=0; //设置普通的IO
GpioCtrlRegs.GPADIR.bit.GPIO1=0; //设置为输入
GpioCtrlRegs.GPAQSEL1.bit.GPIO1=2; //设置为6倍采样时间
GpioCtrlRegs.GPACTRL.bit.QUALPRD0=0xff;//每倍采样时间为510*SYSCLKOUT;
这里对GPIO0进行操作,是因为后面需要将GPIO0作为INT1的中断源。
先将GPIO0设置为普通IO,且设置为输入模式,其次使其时钟

GPIO1和GPIO2在GPAQSEL1,当为0设置0是,使其采样率为系统时钟,但是设为2时,设置采样率为六倍时钟。

GpioIntRegs.GPIOXINT1SEL.bit.GPIOSEL=0; //定义GPIO为XINT1的来源
GpioIntRegs.GPIOXINT2SEL.bit.GPIOSEL=1; //定义GPIO1为XINT2的来源


可以得出GPIO0为XINT1的中断来源,GPIO1为XINT2的时钟来源
// Configure XINT1 and XINT2
XIntruptRegs.XINT1CR.bit.POLARITY=0; //定义为下降沿触发
XIntruptRegs.XINT2CR.bit.POLARITY=1; //定义为上升沿触发
// Enable XINT1 and XINT2
XIntruptRegs.XINT1CR.bit.ENABLE=1; //使能XINT1
XIntruptRegs.XINT2CR.bit.ENABLE=1; //使能XINT2

以上为内容为外部中断初始化代码
下面
void External_Control(void)
{
Uint32 TempX1Count=0;
Uint32 TempX2Count=0;
TempX1Count=Xint1Count;
TempX2Count=Xint2Count;
// Trigger both XINT1
GpioDataRegs.GPBSET.bit.GPIO34=1; //把GPIO拉高
GpioDataRegs.GPBCLEAR.bit.GPIO32=1; //拉低GPIO32,触发XINT1
while(Xint1Count==TempX1Count){}
// Trigger both XINT2
GpioDataRegs.GPBSET.bit.GPIO34=1; //把GPIO拉高
DELAY_US(DELAY);
GpioDataRegs.GPBSET.bit.GPIO33=1; //拉高GPIO33,触发XINT2
while(Xint2Count==TempX2Count){}
if(Xint1Count==TempX1Count+1&&Xint2Count==TempX2Count)
{
LoopCount++;
GpioDataRegs.GPBCLEAR.bit.GPIO33=1; //拉低GPIO33,停止触发XINT2
GpioDataRegs.GPBSET.bit.GPIO32=1; //拉高GPIO32,停止触发XINT1
}
else
{
__asm(" ESTOP0");//停止到这里
}
这个为外部中断测试函数,用GPIO34连接的LED灯进行指示外部中断的进程。GPIO33和GPIO32分别产生上升沿和下降沿
输入给GPIO1,GPIO0,从而触发XINT1,XINT2中断。
__interrupt void xint1_isr(void)
{
GpioDataRegs.GPBCLEAR.all=0x4; //GPIO34拉低
Xint1Count++;
// Acknowledge this interrupt to get more from group 1
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
}
__interrupt void xint2_isr(void)
{
GpioDataRegs.GPBCLEAR.all=0x4; //GPIO34拉低
Xint2Count++;
// Acknowledge this interrupt to get more from group 1
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
}
上述两段程序时中断服务程序,

完毕
本文介绍了TMS320x2806x微控制器的外部中断配置过程,包括中断初始化、中断使能及中断服务程序等内容。通过实例详细解析了如何设置GPIO作为中断源并实现中断触发。
1万+

被折叠的 条评论
为什么被折叠?



