利用WinCE的精准计时函数来输出pwm信号以便控制舵机
FL2440的板子只有TOUT0和TOUT1引出了扩展管脚,而TOUT0与GPB0复用,GPB0又连接着蜂鸣器,所以一用TOUT0输出pwm信号蜂鸣器就大叫不止,而TOUT1又因为Wince系统使用Timer1作为系统定时器,所以在Wince下用TOUT1输出pwm信号会马上死机。
本打算用定时器的中断函数来输出pwm信号,但是感觉WinCE封装ADS下的__irq函数很难搞,无意中发现WinCE有比较精准的计时函数,决定干脆用这个来做pwm信号以便控制舵机。
关键代码:
需要头文件:
#include "ceddk.h" #include "pkfuncs.h" #include "Windows.h" #include "Winbase.h"
1、ms级精准延时函数accurateDelay_ms(),主要知识点有LARGE_INTEGER数据类型,QueryPerformanceFrequency()函数来计算计数频率,QueryPerformanceCounter来计算起始计数和终止计数,起始计数与终止计数的差就是过程中产生了多少计数,再用这个过程计数除以计数频率,就是过程消耗的时间,这个时间比较灵活,用0.01进行因子计算就是ms级,用0.00001计算就是微秒级。输入参数n来决定延时n毫秒。
BOOL accurateDelay_ms(double n) //ms级的精确延时函数 { LARGE_INTEGER litmp; LONGLONG QPart1,QPart2; double dfFreq,dfMinus,dfTim; QueryPerformanceFrequency(&litmp); dfFreq = (double)litmp.QuadPart;//获得计数器的时钟频率 QueryPerformanceCounter(&litmp); QPart1 = litmp.QuadPart;//获得当前初始值 do { QueryPerformanceCounter(&litmp); QPart2 = litmp.QuadPart;//获得终止值 dfMinus = (double)(QPart2-QPart1); dfTim = dfMinus/dfFreq; }while(dfTim<0.01*n); return TRUE; }
2、PWM信号产生函数:
功能:先逆时针旋转180度,然后顺时针旋转360度,再逆时针旋转180度回到起始位置。
通过int型变量duojiCnt来控制舵机转到哪个角度,通过每个while函数的第一个accurateDelay()来控制旋转的方向,每个while函数的第二个accurateDelay()来控制旋转快慢,delay()函数是个软件延时函数,delay(200)是为了保证舵机每一次都有充分的时间完成旋转。
duojiCnt = 11; while(duojiCnt > 0) { v_IOPregs->rGPBDAT |= 1<<6; accurateDelay_ms(0.1); v_IOPregs->rGPBDAT &= ~(1<<6); accurateDelay_ms(10); duojiCnt--; } delay(200); duojiCnt = 22; while(duojiCnt > 0) { v_IOPregs->rGPBDAT |= 1<<6; accurateDelay_ms(0.4); v_IOPregs->rGPBDAT &= ~(1<<6); accurateDelay_ms(10); duojiCnt--; } delay(200); duojiCnt = 12; while(duojiCnt > 0) { v_IOPregs->rGPBDAT |= 1<<6; accurateDelay_ms(0.1); v_IOPregs->rGPBDAT &= ~(1<<6); accurateDelay_ms(10); duojiCnt--; } delay(200);