天嵌 ARM开发社区

 找回密码
 注册
查看: 3882|回复: 3

6410定时中断问题

[复制链接]
miaomiao2935 发表于 2012-8-29 10:06:19 | 显示全部楼层 |阅读模式
各位好!我现在在6410上想用定时器2加普通IO模拟PWM功能,但是定时器的中断一直产生不了,请大家帮我看看问题在哪里,卡在这个地方一个多星期了...
BOOL MO_StartPWM()
{        
        v_pPWMRegs->TCNTB2 = 250;
         InitTimer();
        StartTimer();
        return TRUE;
}
//定时器寄存器的初始化
BOOL InitTimer()
{
         DWORD dwIrq = IRQ_TIMER2;
         BOOL bTmp;
         
         //获取逻辑中断号
         bTmp = KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR,
                                        &dwIrq,
                                        sizeof( dwIrq ),
                                        &dwSysIntr,
                                        sizeof( dwSysIntr ),
                                        NULL );
         if (!bTmp)
         {
          RETAILMSG(1,(TEXT("Get system interrupt failed. \n")));
          return FALSE;
         }
         hTimerEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
         bTmp = InterruptInitialize(dwSysIntr,hTimerEvent,0,0);
         if (bTmp)
         {
          RETAILMSG(1,(TEXT("Init interrupt ok! \n")));
         }
         else
         {
          RETAILMSG(1,(TEXT("Init interrupt failed! \n")));
          return FALSE;
         }
        // timer2 interrupt enable, Do not use OR/AND operation on TINTC_CSTAT directly
    v_pPWMRegs->TINT_CSTAT = TINT_CSTAT_INTMASK(v_pPWMRegs->TINT_CSTAT) &~ TIMER2_INTERRUPT_ENABLE;

         // timer2 interrupt status clear, Do not use OR/AND operation on TINTC_CSTAT directly
    v_pPWMRegs->TINT_CSTAT = TINT_CSTAT_INTMASK(v_pPWMRegs->TINT_CSTAT) | TIMER2_PENDING_CLEAR;

         //v_pPWMRegs->TINT_CSTAT |= 1<<4;   //开timer2中断,允许timer4中断发生
         //v_pVICRegs->VIC0INTENABLE |= 1<<25;  //开timer2的使能(相当于关掉mask

          //创建定时器中断线程
         DWORD dwThreadId;
         //hTimerThread = CreateThread(NULL, 0, TimerThread, NULL, CREATE_SUSPENDED, &dwThreadId);
                hTimerThread = CreateThread(NULL, 0, TimerThread, NULL, 0, NULL);
         if (hTimerThread ==NULL)
         {
                OutputDebugString(L"Unable to create Timer IST: %u\r\n");
         }
         else
         {
                 if (!CeSetThreadPriority(hTimerThread,100))
                 {
                        OutputDebugString(L"CeSetThreadPriority ERROR:%d\n");
                 }
         }

         return TRUE;
}
//定时器中断线程
DWORD WINAPI TimerThread(LPVOID lpParameter)
{
         DWORD dwRes = 0;

         while (bTimerThreadRun)
         {
         
          dwRes = WaitForSingleObject(hTimerEvent, INFINITE);
          if (dwRes != WAIT_OBJECT_0)
          {
           MessageBox(NULL,_T("Wait timer event failed."), NULL, MB_OK);
           return 0;
          }
          else
          {
           //MessageBox(NULL,_T("Wait timer event ok."), NULL, MB_OK);
           RETAILMSG(1,(TEXT("OK \n")));

           if (bRes)
           {
                GpioUp();

                RETAILMSG(1,(TEXT("1 \n")));
           }
           else
           {
                GpioDown();

                RETAILMSG(1,(TEXT("0 \n")));
           }
           bRes = !bRes;
          }

          // timer2 interrupt status clear, Do not use OR/AND operation on TINTC_CSTAT directly
       v_pPWMRegs->TINT_CSTAT = TINT_CSTAT_INTMASK(v_pPWMRegs->TINT_CSTAT) | TIMER2_PENDING_CLEAR;

          InterruptDone(dwSysIntr);
         }
         return 1;
}
void StartTimer()
{
        // timer2 interrupt status clear, Do not use OR/AND operation on TINTC_CSTAT directly
    v_pPWMRegs->TINT_CSTAT = TINT_CSTAT_INTMASK(v_pPWMRegs->TINT_CSTAT) | TIMER2_PENDING_CLEAR;
        // timer2 interrupt enable, Do not use OR/AND operation on TINTC_CSTAT directly
    v_pPWMRegs->TINT_CSTAT = TINT_CSTAT_INTMASK(v_pPWMRegs->TINT_CSTAT) |TIMER2_INTERRUPT_ENABLE;

        v_pPWMRegs->TCON &= ~(0x01 << 12); //timer2 stop
        v_pPWMRegs->TCON |= 0x01 << 13; //manual update on, load the counter
        v_pPWMRegs->TCON &= ~(0x01 << 13); //manual update off
         v_pPWMRegs->TCON |= 0x01 << 15; //auto reload
         //v_pPWMRegs->TCON &= ~(0x01 << 10); //output off
         //pTimerReg->TCON |= 0x01 << 10; //output on
         v_pPWMRegs->TCON |= 0x01 << 12;

         //启动线程
         bTimerThreadRun = TRUE;
         ResumeThread(hTimerThread);
}
embedsky_lhh 发表于 2012-8-29 10:39:45 | 显示全部楼层
代码贴全点啊MO_StartPWM 这个在哪调用的,还有你定时器的打点时钟是多少,定多久才到时,这代码中能看出来吗?
 楼主| miaomiao2935 发表于 2012-8-29 10:51:46 | 显示全部楼层
void MO_SetPrescaler(BYTE t_num, BYTE value)
{
                v_pPWMRegs->TCFG0 &= (~0xFF<< 8);
                v_pPWMRegs->TCFG0 |= (value<< 8);                                // 设置定时器 2 的预分频值
       
}
BOOL MO_SetDivider(BYTE t_num, BYTE value)
{
        BYTE tmp;

        if (value > 16)   
                return FALSE;

        for (tmp = 0; tmp < 4; tmp++)
        {
                if ((2 << tmp) == value)
                        break;
        }   

        if (tmp > 4)                    
                return FALSE;                               // value 取值只能为 2,4,8,16

        v_pPWMRegs->TCFG1 &= ~(0x0F << 8);
        v_pPWMRegs->TCFG1 |= (0<< 8);
        v_pPWMRegs->TCFG1 &= ~(0x11 << 10);
        return TRUE;
}
BOOL GIO_IOControl(DWORD hOpenContext, DWORD dwCode, PBYTE pBufIn, DWORD dwLenIn, PBYTE pBufOut, DWORD dwLenOut, PDWORD pdwActualOut)
{
        switch(dwCode)
        {
                case IOCTL_MO_SET_PRESCALER:                                        // 设置预分频值
                        if (dwLenIn >= 2)                                        // 需要2个字节缓冲区
                        {
                                MO_SetPrescaler(pBufIn[0], pBufIn[1]);
                                //bErr = TRUE;       
                        }
                        break;
               
        case IOCTL_MO_SET_DIVIDER:       
                        if (dwLenIn >= 2)                                        // 需要2个字节缓冲区
                        MO_SetDivider(pBufIn[0], pBufIn[1]);        // 设置分频值        (定时器编号, 分频值)  
                        break;
       
        case IOCTL_MO_INITI:       
                        InitTimer();
                        break;
               
        case IOCTL_MO_START:
                        if (dwLenIn >= 3)                                        // 需要3个字缓冲区
                        {
                                DWORD t_num = *((DWORD *)pBufIn);
                                DWORD cycle = *((DWORD *)(pBufIn + 4));
                                DWORD duty = *((DWORD *)(pBufIn + 8));               

                        MO_StartPWM(t_num, cycle, duty);
                        }
                        break;
        default:
                break;
        }

        RETAILMSG(DEBUG_GPIO,(TEXT("GPIO_Control:Ioctl code = 0x%x\r\n"), dwCode));
        return TRUE;
}

应用程序是
#define S3C6410_PCLK        50000000                        // PCLK是50MHz
#define Prescaler0        15                                // 预分频
#define MUX0                8                                // 定时器分频值
#define TCNTB0                250                // 工作频率
//#define TCMPB0                (TCNTB0>>1)                        // 占空比,默认是50%

BYTE prescale[2] = {2, 15};
BYTE divider[2] = {2, 8};
DWORD buff[3] = {2, 250, 125};
void CADC64Dlg::OnBnClickedButton15()
{
        // TODO: 在此添加控件通知处理程序代码
        BOOL ret;
        DWORD IDThread;

        // 设置 PWM0 定时器预分频值
        ret = ::DeviceIoControl(m_gpiodriver, IOCTL_MO_SET_PRESCALER, prescale, 2, NULL, 0, NULL, NULL);
        if (ret != TRUE)
        {
                OnBnClickedButton16();
                MessageBox(_T("设置 PWM0 定时器预分频值失败!"));
                return;
        }
        // 设置PWM0定时器分频值
        ret = ::DeviceIoControl(m_gpiodriver, IOCTL_MO_SET_DIVIDER, divider, 2, NULL, 0, NULL, NULL);
        if (ret != TRUE)
        {
                OnBnClickedButton16();
                MessageBox(_T("设置 PWM0 定时器分频值失败!"));
                return;
        }

        ret = ::DeviceIoControl(m_gpiodriver, IOCTL_MO_INITI,NULL , 0, NULL, 0, NULL, NULL);
        if (ret != TRUE)
        {
                OnBnClickedButton16();
                MessageBox(_T("设置 PWM0 定时器初始化失败!"));
                return;
        }

       
        buff[1] = 250;//freq
        buff[2] = 125;//duty
        //printf("buff[1]=%d\n",buff[1]);

        ret = ::DeviceIoControl(m_gpiodriver, IOCTL_MO_START, buff, 3,  NULL, 0, NULL, NULL);
        if (ret != TRUE)
        {
//                        MessageBox(_T("蜂鸣器启动失败!"));
                        //return 0;
        }
       

}
embedsky_lhh 发表于 2012-8-29 13:22:17 | 显示全部楼层
这个你先看定时器的计数有变化么?他到了你设定的时间才会触发中断,
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

i.MX8系列ARM cortex A53 M4 工控板上一条 /1 下一条

Archiver|手机版|小黑屋|天嵌 嵌入式开发社区 ( 粤ICP备11094220号 )

GMT+8, 2024-5-9 04:40 , Processed in 1.093750 second(s), 22 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表