CC2541 定时器1不能产生中断
今天想要在CC2541上写个外红发射程序,因为要加到BLE中,所以就用定时器1和定时器3配置产生外红信号,考虑到准确性,还用到了DMA通道。
代码基于BLE协议栈的HIDAdvRemote例程,实际上也没用到BLE和OSAL。
思路如下:
初始化:首先使用定时器3比较输出一个38K载波信号(datasheet中有描述)。在使用定时器1的updown模式,置定时器1的通道1为比较输出模式,产生一个前导位。使能定时器1中断。
在等待定时器1产生updown模式的中断。
定时器中断中:在前导位的结束时,产生定时器1的中断,在定时器1的中断中使能DMA,使用DMA来修改定时器1的通道0的比较值,用于改变一个BIT的时间长短。再配置定时器1的通道1为比较输出模式,定时器1为Modulo,在关闭定时器中断。
等待DMA完成中断。
在DMA中断中:关闭定时器1,和3,关闭外红模式,设置定时器1,为updown模式,使能定时器1中断。设置好外红剩余的等待时间,等待中断。
到了这里就出问题了。
设置好定时器1后,就产生不了定时器1的中断。(EA和定时器1中断都已使能!)
下面看下代码。
#include "hal_types.h"
#include "hal_drivers.h"
#include "hal_dma.h"
#include "hal_mcu.h"
#define IR_USERCODE1_OFFSET 0
#define IR_USERCODE2_OFFSET (IR_USERCODE1_OFFSET + 8)
#define IR_DATA1_OFFSET (IR_USERCODE2_OFFSET + 8)
#define IR_DATA2_OFFSET (IR_DATA1_OFFSET + 8)
extern halDMADesc_t dmaCh1234[4];
const unsigned short IR_BIT_TIME[2] = { 46, 84 };//定时器1通道0的发送IR0和1的时寄存器值
const unsigned short IR_BIT_SENDTIME[2] = { 1125, 2250};
unsigned short IR_TIME_BUF[32];
unsigned long IR_TotalTick = 108000;//us
unsigned long IR_HadSendTick = 0;
unsigned long IR_NeedSendTick = 0;
void IR_WrtieByteToBuf(unsigned char Data, unsigned short* IR_Buf)
{
unsigned char i;
unsigned char bit = 1;
unsigned char temp = 0;
for(i=0; i<8; i++)
{
temp = (Data&bit)?1:0;
IR_HadSendTick += IR_BIT_SENDTIME[temp];
IR_Buf[i] = IR_BIT_TIME[temp];
bit <<= 1;
}
}
void IR_SendDataWriteBuf(unsigned char UserCode1, unsigned char UserCode2, unsigned char IR_Data)
{
IR_WrtieByteToBuf(UserCode1, IR_TIME_BUF + IR_USERCODE1_OFFSET);
IR_WrtieByteToBuf(UserCode2, IR_TIME_BUF + IR_USERCODE2_OFFSET);
IR_WrtieByteToBuf(IR_Data, IR_TIME_BUF + IR_DATA1_OFFSET);
IR_WrtieByteToBuf(~IR_Data, IR_TIME_BUF + IR_DATA2_OFFSET);
}
unsigned char Timer1_Irq_statue;
void DMA_CH1_Irq(void)
{
//DMA完成中断
IRCTL = 0x00;//关闭红外
T3CCTL0 = 0x40;
T3CTL = 0x00;//关闭载波
T1STAT = 0x00;
TIMIF = 0x00;
T1CCTL1 = 0x40;
T1CTL = 0x00;
T1IF = 0;//如果加了这句话,就产生不了中断,但是如果不加,则定时器1马上产生中断!
//IR发送在32M时最大需要发送54000us,小于65535
IR_NeedSendTick = IR_NeedSendTick>>1;//采用up down模式
T1CC0L = (unsigned char)IR_NeedSendTick;
T1CC0H = IR_NeedSendTick>>8;
Timer1_Irq_statue = 2;
T1IE = 1;
T1CTL = 0x0B;
}
void Timer1_Irq_Fun(void);
HAL_ISR_FUNCTION( Timer1_Irq, T1_VECTOR )
{
HAL_ENTER_ISR();
Timer1_Irq_Fun();
T1IF = 0;
T1STAT = 0;
HAL_EXIT_ISR();
return;
}
void Timer1_Irq_Fun(void)
{
switch(Timer1_Irq_statue)
{
case 0://引导码结束中断
if(!(T1STAT&0x20))
{
return ;
}
T1CNTL = 0;
T1CCTL1 = 0;
DMAARM |= 0x02;//DMA使能
T1IE = 0;//取消中断,等待数据段发送完成
T1CC0L = IR_TIME_BUF[0];//84,46
T1CC0H = IR_TIME_BUF[0]>>8;
T1CC1L = 21;//21
T1CC1H = 0;
T1CCTL1 = 0x64;
T1CCTL1 = 0x7C; //比较输出模式100
T1CTL = 0x02;//00001110
break;
case 2: //计算剩余时间结束
Timer1_Irq_statue = 0;//跑不到这里
T1CTL = 0x00;
T1CCTL1 = 0x00;
T1STAT = 0x00;
T1IE = 0;
P0SEL &= ~BV(3);
P0DIR &= ~BV(3);
P0 &= ~BV(3);
break;
}
}
int main(void)
{
HAL_BOARD_INIT();
osal_int_disable( INTS_ALL );
P0SEL |= BV(3);
P0DIR |= BV(3);
PERCFG = 0x33;
IR_HadSendTick = 0;
IR_SendDataWriteBuf(0x0E,0x0E,0xAA);
IR_NeedSendTick = IR_TotalTick - IR_HadSendTick - 9000 + ((IR_TIME_BUF[31] == IR_BIT_TIME[0])?565:1690);
dmaCh1234[0].srcAddrH = (unsigned short)IR_TIME_BUF>>8;
dmaCh1234[0].srcAddrL = (unsigned short)IR_TIME_BUF;
dmaCh1234[0].dstAddrH = 0x62;
dmaCh1234[0].dstAddrL = 0xA6;
dmaCh1234[0].xferLenV = 0x20;
dmaCh1234[0].xferLenL = 32;
dmaCh1234[0].ctrlA = 0x83;
dmaCh1234[0].ctrlB = 0x49;
HalDmaInit();
Timer1_Irq_statue = 0;
//38K载波
T3CTL = 0x46;//Tickfrequency/4,Overflow Interrupt is disabled,Modulo,CLR
T3CC0 = 211;
T3CCTL1 = 0x64;//Channel 1 interrupt is enabled, Clear output on compare-up,Compare mode,No capture
T3CC1 = 70;
T3CTL = 0x52;//01010010
IRCTL = 0x01;
T1IF = 0;
T1IE = 1;
T1CNTL = 0;
T1CCTL1 = 0;
T1CC0L = 254;//84,46
T1CC0H = 0;
T1CC1L = 169;//21,224
T1CC1H = 0;
T1CCTL1 = 0x5C;
T1CCTL1 = 0x7C;
T1CTL = 0x03;//使用updown模式产生前导位
HAL_ENABLE_INTERRUPTS();
while(1);
}
如下代码是time1 PWM定时器中断配置,供参考
T1CTL = 0x0A; // Div = 32, CLR, MODE = module ;PWM = 2.04MS
T1CCTL1 = 0x24; // IM = 0; CMP = Clear output on compare; Mode = Compare
T1CNTL = 0; // Reset timer to 0;
T1CNTH = 0; // Reset timer to 0;
//必须设置,否则定时器不工作
T1CCTL0 = 0x64; // IM = 1, CMP = Clear output on compare; Mode = Compare
T1CC0H = (0xff>>SFT_LBIT); // Ticks = 375 (2.4ms)
T1CC0L = (uint8)((0xff<<SFT_RBIT)); // Ticks = 375 (2.4ms)
IEN1 |= 0x26; // Enable T1 cpu interrupt
IEN0 |= 0x80;