本帖最后由 fish001 于 2017-4-26 19:56 编辑
编了一个MSP430f169 捕获8路PWM波信号的程序。分别用定时器B的所有捕获比较寄存器以及定时器A的一个捕获比较寄存器进行捕获。结果只有TBCCR0和TBCCR1捕获的两路信号是对的,其他几路都不对。实在找不出哪出问题了,各位前辈帮我看一下。下面是代码。
主函数代码:
C/C++ code
/*********************************************************
程序功能:分别检测加速度计模块从P4.0到P4.6端口输入的PWM波
信号的T1和T2(T1为高电平脉宽,T2为周期),并将数
据通过串口发送到PC(理想PWM波周期1600us情况下)
-----------------------------------------------------------
通信格式:N.8.1, 9600
-----------------------------------------------------------
**********************************************************/
#include
#include "UART0_Func.c"
#include "function.c"
//#define M1 16
//unsigned int cap1=0,cap2=0,N1=0,N2=0;
unsigned int cap[8]={0,0,0,0,0,0,0,0};//存放捕获是6路信号各自的上升沿时计数器的数值
unsigned int n[8]={0,0,0,0,0,0,0,0};//存放计数溢出的次数
long widthT01[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
long widthT02[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};//存放每路信号的高点平宽度和周期信息
long widthT03[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
long widthT04[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
long widthT11[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
long widthT12[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
long widthT13[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
long widthT14[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
long widthT21[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
long widthT22[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
long widthT23[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
long widthT24[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
long widthT31[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
long widthT32[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
long widthT33[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
long widthT34[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
//char m=0,n=0,a=0,b=0;
char m[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};//用于记录每路数据已经采集了的个数,每路信号采集M1个数,
long XT1[4]={0,0,0,0};//存放8路信号取平均后的值。
long XT2[4]={0,0,0,0};
long YT1[4]={0,0,0,0};
long YT2[4]={0,0,0,0};
unsigned char data_T[34];//存放将要发送的数据
void main( void )
{
char k1;
// Stop watchdog timer to prevent time out reset
WDTCTL = WDTPW + WDTHOLD;//关闭看门狗
//-------开晶振XT2---------
BCSCTL1&=~XT2OFF; //打开XT2振荡器
do
{
IFG1 &= ~OFIFG; // 清除振荡器失效标志
for (int i=256;i>0;i--); // 延时,等待XT2起振
}
while ((IFG1 & OFIFG) != 0); // 判断XT2是否起振 */
IFG1&=~OFIFG;
BCSCTL2=SELM1+SELS+DIVS0+DIVS1;//SMCLK=XT2,8分频
P4SEL|=BIT0+BIT1+BIT2+BIT3+BIT4+BIT5+BIT6;////P4.0和P4.1作为捕获模块功能输入端输入方波
//TBCCTL0=0;//捕获源为P4.0,即CCI0A(也是CCI0B)
P1DIR = BIT0+BIT4; //设置P1.0方向为输出
P1SEL = BIT2; //设置P1.2端口为功能模块使用
TACTL = TACLR+TASSEL_2+TAIE+MC1;
//==定时器A时钟信号选择SMCLK,8分频,同时设置定时器A计数模式为连续增计模式==
TACCTL1|=CM_1+SCS+CAP+CCIE; //MC0
//输入上升沿捕获,CCI0A为捕获信号源
TBCCTL0|=CM_1+SCS+CAP+CCIE;//上升沿捕获,同步捕获,工作在捕获模式+中断允许
TBCCTL1|=CM_1+SCS+CAP+CCIE;//上升沿捕获,同步捕获,工作在捕获模式+中断允许
TBCCTL2|=CM_1+SCS+CAP+CCIE;//上升沿捕获,同步捕获,工作在捕获模式+中断允许
TBCCTL3|=CM_1+SCS+CAP+CCIE;//上升沿捕获,同步捕获,工作在捕获模式+中断允许
TBCCTL4|=CM_1+SCS+CAP+CCIE;//上升沿捕获,同步捕获,工作在捕获模式+中断允许
TBCCTL5|=CM_1+SCS+CAP+CCIE;//上升沿捕获,同步捕获,工作在捕获模式+中断允许
TBCCTL6|=CM_1+SCS+CAP+CCIE;//上升沿捕获,同步捕获,工作在捕获模式+中断允许
TBCTL|=TBSSEL_2+MC_2+TBIE;//选择SMCLK+连续计数模式
//+终端允许
InitUART();//初始化UART端口
_EINT();//中断允许
while(1)
{
for(k1=0;k1
{
XT1[0]+=widthT01[k1];
XT2[0]+=widthT02[k1];
YT1[0]+=widthT03[k1];
YT2[0]+=widthT04[k1];
XT1[1]+=widthT11[k1];
XT2[1]+=widthT12[k1];
YT1[1]+=widthT13[k1];
YT2[1]+=widthT14[k1];
XT1[2]+=widthT21[k1];
XT2[2]+=widthT22[k1];
YT1[2]+=widthT23[k1];
YT2[2]+=widthT24[k1];
XT1[3]+=widthT31[k1];
XT2[3]+=widthT32[k1];
YT1[3]+=widthT33[k1];
YT2[3]+=widthT34[k1];
}
XT1[0]>>= 4;
XT2[0]>>= 4;
YT1[0]>>= 4;
YT2[0]>>= 4;
XT1[1]>>= 4;
XT2[1]>>= 4;
YT1[1]>>= 4;
YT2[1]>>= 4;
XT1[2]>>= 4;
XT2[2]>>= 4;
YT1[2]>>= 4;
YT2[2]>>= 4;
XT1[3]>>= 4;
XT2[3]>>= 4;
YT1[3]>>= 4;
YT2[3]>>= 4;//求和取平均
if(n[0]==0)
{
Hex2Dec(0,XT1,XT2,YT1,YT2,data_T);//将第一对信号放入data_T数组准备发送
Hex2Dec(1,XT1,XT2,YT1,YT2,data_T);//第二对信号
Hex2Dec(2,XT1,XT2,YT1,YT2,data_T);//第三对信号
Hex2Dec(3,XT1,XT2,YT1,YT2,data_T);//第四对信号
//数据转为char型进行传输
//数据每路PWM波周期为1600us,每路信号用4bit就可把数据表示完整
//T1用data_T的前2位,T2用后2位,低位在前
//前4位存X轴数据,后4位存Y轴数据
PutString(data_T);
}
}
// return 0;
}
//全局变量可以通过中断服务程序改,只要函数中没有相同的局部变量就行
#pragma vector=TIMERB0_VECTOR
__interrupt void TimerB0(void)//定时器TB的CCR0的中断,用于检测脉冲上升与下降
{
Capture_B(0,m,cap,n,widthT01,widthT02);
}
//Timer_B7 Interrupt Vector(TBIV) handler
#pragma vector=TIMERB1_VECTOR
__interrupt void Timer_B(void)//定时器TB的CCR1的中断,
{
//TBCCTL0&=~BIT0;
switch(TBIV)
{
case 2:
Capture_B(1,m,cap,n,widthT03,widthT04);
break;/**/
case 4:
Capture_B(2,m,cap,n,widthT11,widthT12);
break;/**/
case 6:
Capture_B(3,m,cap,n,widthT13,widthT14);
break;/**/
case 8:
Capture_B(4,m,cap,n,widthT21,widthT22);
break;/**/
case 10:
Capture_B(5,m,cap,n,widthT23,widthT24);
break;/**/
case 12:
Capture_B(6,m,cap,n,widthT31,widthT32);
break;/**/
case 14:n[0]++,n[1]++,n[2]++,n[3]++,n[4]++,n[5]++,n[6]++;break;//溢出
}
}
#pragma vector=TIMERA1_VECTOR //定时器A中断处理
__interrupt void timer_a(void)
{
switch(TAIV) //向量查询
{ case 2: //捕获中断
Capture_A(1,m,cap,n,widthT33,widthT34);
break;
case 10: //定时器溢出中断
n[7]++; break; //溢出计数加1
default:break;
}
}
串口通讯-UART0_Func.c文件代码:
C/C++ code
#include
typedef unsigned char uchar;
/*******************************************
函数名称:InitUART
功 能:初始化UART端口
参 数:无
返回值 :无
********************************************/
void InitUART(void)
{
P3SEL |= 0x30; // P3.4,5 = USART0 TXD/RXD
ME1 |= URXE0 + UTXE0; // Enable USART0 T/RXD
UCTL0 |= CHAR; // 8-bit character
UTCTL0 |= SSEL0; // UCLK = ACLK
UBR00 = 0x03; // 32k/9600 - 3.41
UBR10 = 0x00; //
UMCTL0 = 0x6B; // Modulation
UCTL0 &= ~SWRST; // Initialize USART state machine
}
/*******************************************
函数名称:Send1Char
功 能:向PC机发送一个字符
参 数:sendchar--要发送的字符
返回值 :无
********************************************/
void Send1Char(uchar sendchar)
{
while (!(IFG1 & UTXIFG0)); //等待发送寄存器为空
TXBUF0 = sendchar;
}
/*******************************************
函数名称:PutSting
功 能:向PC机发送字符串,无换行
参 数:ptr--指向发送字符串的指针
返回值 :无
********************************************/
void PutString(uchar *ptr)
{
int i;
for(i=0;i<34;i++)
{
Send1Char(ptr); // 发送数据
}
}
/********************************************
函数名称:Hex2Dec
功 能:将long型数据变换成char型的形式
参 数:Hex_Val--long型数据
ptr--指向存放转换结果的指针
返回值 :无
********************************************/
void Hex2Dec(unsigned char channel,long *XT1,long *XT2,long *YT1,long *YT2,uchar *ptr)
{
int i;//数组ptr有34bit,2bit标注位,32bit数据位。
unsigned char num=channel*8;//channel取0到3.
ptr[0]=ptr[1]=0xFF;//作为标志位//,XT1,XT2,YT1,YT2,data_T
for(i=0;i<2;i++)//存放占空比信号,此时低位在前
{
ptr[i+num+2]=XT1[channel]%256;//存放X轴高电平宽度
ptr[i+num+4]=XT2[channel]%256;//存放X轴周期
ptr[i+num+6]=YT1[channel]%256;//存放Y轴高电平宽度
ptr[i+num+8]=YT2[channel]%256;//存放Y轴周期
XT1[channel]>>= 8;
XT2[channel]>>= 8;
YT1[channel]>>= 8;
YT2[channel]>>= 8;
}
}
功能函数-function.c文件代码:
C/C++ code
?
#include
//typedef unsigned char uchar;
#define M1 16
void Capture_B(unsigned short channel,char *m,unsigned int *cap,unsigned int *n,long *widthT1,long *widthT2)
{
volatile unsigned short *tbcctlx,*tbccrx;//设置指向相应寄存器的指针
unsigned char num=channel*2;//channel取0到6.
tbcctlx=&TBCCTL0+channel;//0x0182u为TBCCTL0地址,相邻两个控制寄存器地址相差2.确定相应通道。
tbccrx=&TBCCR0+channel;//0x0192u为地址。当channel==0,指向TBCCR0。
//当channel==1,指向TBCCR1.以此类推。
if(*tbcctlx&CM1)//捕获到下降沿
{
widthT1[m[num]++]=65536*n[channel]+*tbccrx-cap[channel];//记录下结束时间,保存高电平宽度
//N1=0;
//cap1=TBCCR0;//添加这段的话,T2将保存低电平的宽度
*tbcctlx=CM_1+SCS+CAP+CCIE;//+TBCLR;
//改为上升沿捕获,CM0置1,CM1置0
if(m[num]==M1) m[channel]=0;
}
else if(*tbcctlx&CM0)//捕获到上升沿
{
widthT2[m[num+1]++]=65536*n[channel]+*tbccrx-cap[channel];//记录下结束时间,保存周期宽度
n[channel]=0;
cap[channel]=*tbccrx;//始终保存上升沿时的数值
*tbcctlx=CM_2+SCS+CAP+CCIE;//+TBCLR;
//改为下降沿捕获,CM0置0,CM1置1
if(m[num+1]==M1) m[num+1]=0;
}
}
void Capture_A(unsigned short channel,char *m,unsigned int *cap,unsigned int *n,long *widthT1,long *widthT2)
{
volatile unsigned short *tacctlx,*taccrx;//设置指向相应寄存器的指针
// unsigned char num=channel*2;//channel取0到6.
tacctlx=&TACCTL0+channel;//0x0162u相邻两个控制寄存器地址相差2.确定相应通道。
taccrx=&TACCR0+channel;//0x0172u当channel==0,指向TACCR0。
//当channel==1,指向TACCR1.以此类推。
if(*tacctlx&CM1)//捕获到下降沿
{
widthT1[m[7]++]=65536*n[7]+*taccrx-cap[7];//记录下结束时间,保存高电平宽度
//N1=0;
//cap1=TBCCR0;//添加这段的话,T2将保存低电平的宽度
*tacctlx=CM_1+SCS+CAP+CCIE;//+TBCLR;
//改为上升沿捕获,CM0置1,CM1置0
if(m[14]==M1) m[14]=0;
}
else if(*tacctlx&CM0)//捕获到上升沿
{
widthT2[m[15]++]=65536*n[7]+*taccrx-cap[7];//记录下结束时间,保存周期宽度
n[7]=0;
cap[7]=*taccrx;//始终保存上升沿时的数值
*tacctlx=CM_2+SCS+CAP+CCIE;//+TBCLR;
//改为下降沿捕获,CM0置0,CM1置1
if(m[15]==M1) m[15]=0;
}
}