基于PCA模块的16位捕获模式解析PPM信号

/*这是利用PCA模块解析PPM信号的代码,其中uart_send.h头文件是我之前编写的串口通信例程,现在-
  利用串口通信将解析的PPM信号发送给PC端,而PCA模块解析代码的绝大部分我都是基于STC14F2K60S2
  的用户手册的参考例程所编写,intrins.h文件是参考例程中所引用的文件,具体作用我并未进行了解
  其中,我利用串口确实接收到了一批数据,但并未检验数据的正确性。我在下面也贴出了程序中所预编
  译的文件,肯能会比较啰嗦,这是因为所包含的文件中还有其他功能的函数设置。*/


#include <uart_send.h>
#include <STC15F2K60S2.H>
#include <intrins.h>

//===========function statement===================
void IO_set();
void PAC_init();
void StarPCA();


unsigned char cnt;
unsigned long count0;
unsigned long count1;
unsigned long length;
bit busy=0;






void main()
{
	IO_set();
	PAC_init();
	init();
	Enable_Interrupt();
	Staruart();
	StarPCA();
	while(1)
	{
		if(busy)
		{
            if(busy)
            {
                busy = 0;
                if(length<65535)                      //CCAP寄存器最大值,数据时间小于这么多
                {
			        tuart((unsigned char)(length)>>8);
			        tuart((unsigned char)length);
                }
            }
		}
	}
	
	
}

void PCA_Interrupt() interrupt 7
{
	if(CF)
	{
		CF=0;
		cnt++;
	}
	if(CCF0)
	{
		CCF0=0;
		count0=count1;
		((unsigned char *)&count1)[3]=CCAP0L;
		((unsigned char *)&count1)[2]=CCAP0H;
		((unsigned char *)&count1)[1]=cnt;
		((unsigned char *)&count1)[0]=0;
		length = count1-count0;
        busy = 1;
	}
}


void IO_set()
{
	ACC = P_SW1;
	ACC &= ~(0X10|0X20);
	P_SW1 = ACC;
}


void PAC_init()
{
	CCON = 0;		//PCA Control Register setting & PCA Timer Stop & Clear CF &Clear Interrupt Flag
	
	CL = 0;		//reset PCA Register 
	CH = 0;		//reset PCA Register
	
	CCAP0L = 0;		//reset PCA Register
	CCAP0H = 0;		//reset PCA Register
	
	CMOD = 0X09;		//set PCA system clock & enable PCA Timer overflow Interrupt 
	
	CCAPM0 = 0X21;			//PCA--CCP16bitmode setting & rising edge mode & measure T
}

void StarPCA()
{
	CR = 1;
}

 

#include <STC15F2K60S2.H>

void init();
void Staruart();
unsigned char ruart();
void tuart(unsigned char trdate);
void delay_ms(unsigned short i);
void Enable_Interrupt();

#define FOSC 24000000

//sfr	P_SW1 = 0XA2;		//外设功能切换寄存器1

sfr	CCON = 0XD8;		//PCA控制寄存器
//sbit	CCF0 = CCON^0;		//PCA模块0中断标志
//sbit	CR = CCON^6;		//PCA定时器运行控制位
//sbit	CF = CCON^7;		//PCA定时器溢出标志

//sfr	CMOD = 0XD9;		//PCA模式寄存器

//sfr	CL = 0XE9;		//PCA定时器低字节
//sfr	CH = 0XF9;		//PCA定时器高字节

//sfr	CCAPM0 = 0XDA;		//PCA模块0模式寄存器
//sfr	CCAP0L = 0XEA;		//PCA模块0捕获寄存器LOW
//sfr	CCAP0H = 0XFA;		//PCA模块0捕获寄存器HIGH
#include <uart_send.h>

//#define FOSC 12000000
#define BAUD1 9600

#define TIMEDATE (65536-120)

bit Tflag=0;
bit Rflag=0;

unsigned char channel0=0;


#define	S2RI	0X01

sbit CHANNEL0=P2^0;


void init();
void Staruart();
unsigned char ruart();
void tuart(unsigned char trdate);
void delay_ms(unsigned short i);
void Enable_Interrupt();

sbit LED=P2^0;

unsigned char date[12];


//void main()
//{
//	unsigned char count;
//	init();
//	delay_ms(10);
//	Staruart();
//	channel0=0;
//	delay_ms(2000);
//	channel0=0;
//	delay_ms(2000);
//	channel0=100;
//	while(channel0--)
//	{
//		delay_ms(1000);
//	}
//	while(1)
//	{
//		if(date[11])
//		{
//		for(count=0;count<11;count++)
//		{
//			tuart(date[count]);
//		}
//		}
//	}

//}


void uart2() interrupt 8
{
	static i=0;
	if(S2CON&S2RI)
	{
		S2CON&=~S2RI;
		date[i++]=S2BUF;
		if(date[0]!=0x55)
		{
			i=0;
			date[11]=0;
		}
		else
		{
			date[11]=1;
		}
		if(i==11)
		{
			i=0;
		}
		
	}
}


void uart() interrupt 4
{
	if(RI)
	{
		RI=0;
		Rflag=1;
	}
	if(TI)
	{
		TI=0;
		Tflag=1;
	}
}

void PWM() interrupt 1
{
	static i=0;
	i++;
	if(i<=(channel0+100))
	{
		CHANNEL0=1;
	}
	else
	{
		CHANNEL0=0;
	}
	if(i==2000)
	{
		i=0;
	}
}
		
		


void delay_ms(unsigned short i)
{
unsigned short k;
	while(i--)
	for (k=0;k<100;k++); 
}

void init()
{
	SCON=0X50;		//UART1 SETTING
	ES=1;					//UART1	INTERRUPT
	
	S2CON=0X50;		//UART2	SETTING
	IE2=0X01;     //UART2 INTERRUPT 
	
	AUXR=0X14;		//UART1 AND UART2
	AUXR|=0X01;		//UART1 AND UART2
	AUXR|=0X80;		//TIME0 SETTING
	
	T2L=(65536-(FOSC/4/BAUD1));				//BAUD SETTING
	T2H=(65536-(FOSC/4/BAUD1))>>8;

	
	delay_ms(10);
	
	TMOD=0X00;
	TL0=TIMEDATE;
	TH0=TIMEDATE>>8;
	TR0=1;
	ET0=1;
	
	CHANNEL0=0;
}

	
void Staruart()
{
	unsigned char c;
	c=0xff;
	SBUF=c;
	c=SBUF;
}

void Enable_Interrupt()
{
	EA = 1;
}



unsigned char ruart()
{
	unsigned char redate;
	while(~Rflag);
	if(Rflag)
		{
			Rflag=0;
			redate=SBUF;
		}
		return redate;

}


void tuart(unsigned char trdate)
{
	while(~Tflag);
	if(Tflag)
	{
		Tflag=0;
		SBUF=trdate;
	}
}

PS:我之所以想到要解析PPM信号是因为我在使用内部时钟频率的STC15F2K60S2这一单片机解析SBUS协议信号时发现,无论我如何修改代码,似乎SBUF这个寄存器永远都没有接收到数据,一直是0X00,这就使我非常沮丧,而我暂时认为是单片机的性能不够。由于我最后的卑微的一丝丝倔强(没钱买32,还没学过32),我决定不更换单片机,当我知道还有这个PPM协议的时候,我顿时感觉豁然开朗。其实还有其他博主不是使用PCA模块的捕捉功能,也可以使用定时器延时之类的方式实现解析PPM。但是我认为,能够硬件完成的东西,我肯定不会用软件实现。有问题吗?没有问题!实际上是因为我太菜啦,软件方式搞来搞去,头都晕了,直接操作寄存器它不香吗。这个程序其实是第一次调成功的,其中必然还有很多很多的漏洞,但是作为一个乐观主义者,能接收到数据不就是一个巨大的成功了吗。总比我之前用SBUS接收一整个屏幕的零蛋好吧。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值