首页程序设计C51程序基于STC11F04E单片机的信号发生器之程序设计

基于STC11F04E单片机的信号发生器之程序设计

时间2015-07-27 22:26:17发布caterwang分类C51程序浏览3335

前机有文章已经提到过硬件电路的设计了,这里主要描述程序的设计,以下代码就是信号发生器的主体代码,其他的程序函数因与其他文章重复,故不再贴出。

/******************************************************************************
单片机:STC11F04E,晶振:22.1184MHZ
时间:2012.12.01
全新的输出波形

时间:2015.05.12
修正反三角输出波形不完整的问题
******************************************************************************/
#include "IODefine.h"
#include "DADriver.h"
#include "DADriver_main.h"
#include "math.h"
#define DEBUG 0	//调试时设为1,否则设为0
/****************************************************
*10us延时子程序
*用示波器调试过的延时程序@22.1184MHz
****************************************************/
void Del10us(unsigned n) 
 	{
	unsigned char i;
	while(n--)							  
		{
		_nop_();
		i = 50;
		while (--i);
		}
	}
void Del50us(unsigned n)
{
	unsigned char i, j;
	while(n--)
	{
		i = 1;
		j = 60;
		do
		{
			while (--j);
		} while (--i);
	}	
}
void Del100us(unsigned n)		//@22.1184MHz
{
	unsigned char i, j;
    while(n--)
		{
		_nop_();
		_nop_();
		i = 3;
		j = 34;
		do
		{
			while (--j);
		} while (--i);
	}
}
void Del2ms_DA(unsigned int k,int m,int n,int z)
{
	while(k--)
	{
		WriteTLC5615(m);
		Del100us(1);
		WriteTLC5615(z);
		Del100us(4);

		WriteTLC5615(n);
		Del100us(1);
		WriteTLC5615(z);
		Del100us(4);
	}
}
void main(void)
{
unsigned int DianYamax;		//电压
unsigned char BoXing;		//波形
unsigned int TimeCtl;
int i,m,n,k,dd;
int m1,n1,z1;			   
float sin;
SysConfig();
WriteTLC5615(512);	//上电时确保输出电压为0
#if DEBUG
//------------测试输出波形-----------------
TimeCtl = 200;//100*buf[3]
RunFlag = 1;
BoXing  = 4;
DianYamax = 100+1*9;//1023-->5V,818-->4V,409-->2V
sin = DianYamax/530.0;
//------------测试输出波形-----------------	
#endif
while(1)
	{
	 if(RunFlag) //系统处于运行状态--即治疗状态
	 {
		 switch(BoXing)
		 {
		//以下波形,疏[150HZ],密[500HZ],其他[500HZ]
		case 1:	//疏--150Hz
			WriteTLC5615(512);
			TimeOutS = 0;			 
			TimeOutD = TimeCtl/10;
			TR0 =1;
			while(TimeOutS<TimeOutD) //超时等待
				{
				WriteTLC5615(512+DianYamax);	 //0.05ms=50us	,脉冲宽度为200us
				Del50us(16);
				WriteTLC5615(512);
	
				Del50us(250);			 	//3.33ms-0.05ms=3.28ms
	
			    WriteTLC5615(512-DianYamax);	  //50us
				Del50us(16);
				WriteTLC5615(512);
	
				Del50us(250);
				}
			TR0 =0;
			WriteTLC5615(512);
		 	break;
		
		case 2:	  	//密--500Hz
			WriteTLC5615(512);
			TimeOutS = 0;			 
			TimeOutD = TimeCtl/10;
			TR0 =1;
			while(TimeOutS<TimeOutD) //超时等待
				{
				WriteTLC5615(512+DianYamax);	 //0.05ms=50us
				Del50us(16);
				WriteTLC5615(512);
	
				Del50us(62);			 		//1ms-0.05ms=0.95ms=950us
	
			    WriteTLC5615(512-DianYamax);	  //50us
				Del50us(16);
				WriteTLC5615(512);
	
				Del50us(62);			 	//1ms-0.05ms=0.95ms=950us
				}
			TR0 =0;
			WriteTLC5615(512);
			break;
			
		case 3:		//疏密
			WriteTLC5615(512);
			TimeOutS = 0;			 
			TimeOutD = TimeCtl/10;
			TR0 =1;
			while(TimeOutS<TimeOutD) //超时等待
				{
				WriteTLC5615(512+DianYamax);	 //0.05ms=50us
				Del50us(16);
				WriteTLC5615(512);
	
				Del50us(62);			 	//1ms-0.05ms=0.95ms=950us
	
			    WriteTLC5615(512-DianYamax);	  //50us
				Del50us(16);
				WriteTLC5615(512);
	
				Del50us(62);			 	//1ms-0.05ms=0.95ms=950us
				}
			TR0 =0;
			/*----------------------------------------------------*/
			WriteTLC5615(512);
			TimeOutS = 0;			 
			TimeOutD = TimeCtl/10;
			TR0 =1;
			while(TimeOutS<TimeOutD) //超时等待						
				{
				WriteTLC5615(512+DianYamax);	 //0.05ms=50us	,脉冲宽度为200us
				Del50us(16);
				WriteTLC5615(512);
	
				Del50us(250);			 	//3.33ms-0.05ms=3.28ms
	
			    WriteTLC5615(512-DianYamax);	  //50us
				Del50us(16);
				WriteTLC5615(512);
	
				Del50us(250);
				}
			TR0 =0;
			WriteTLC5615(512);
			break;
			
		case 4:	   	//正三角
			m=512;													
			n=512;
			//TimeCtl是时间,单位为ms ,DianYamax是电压最大值,k是数据更新的频率
			if(TimeCtl>=DianYamax)
				{
				k=TimeCtl/DianYamax;
				dd=1;
				}
			else
				{
				k=1;
				dd=DianYamax/TimeCtl;
				}
			for(i=0;i<TimeCtl;i++)
				{
				Del2ms_DA(1,m,n,512);  //1ms
				if((i%k)==0)	//控制多少时间更新一次数据
					{
					m+=dd;
					n-=dd;
					}
				if(m>1000)
					{
					//k=i;
					break;
					}
				}
			for(i=0;i<TimeCtl;i++)
				{
				Del2ms_DA(1,512,512,512);
				//if(i>=k)
				//	break;
				}
			break;

		case 5:		//反三角
			m=512-DianYamax;
			n=512+DianYamax;
			if(TimeCtl>=DianYamax)
				{
				k=TimeCtl/DianYamax;
				dd=1;
				}
			else
				{
				k=1;
				dd=DianYamax/TimeCtl;
				}
			for(i=0;i<TimeCtl;i++)
				{
				Del2ms_DA(1,m,n,512);  //1ms
				if((i%k)==0)	//控制多少时间更新一次数据
					{
					m+=dd;
					n-=dd;
					}
				if(m>512)
					{
					m=500;
					n=524;
					Del2ms_DA(1,m,n,512);  //1ms
					//k=i;
					break;
					}
				}
			for(i=0;i<TimeCtl;i++)
				{
				Del2ms_DA(1,512,512,512);
				//if(i>=k)
				//	break;
				}
			break;
		case 6:				//手针(Del10us)
		case 7:
			sin = DianYamax/530.0;
			m=0;
			n=64;
			m1=(int)(Sin128N[m]*(sin));
			n1=(int)(Sin128N[n]*(sin));
			z1=(int)(Sin128N[0]*(sin));
			k=TimeCtl/32;
			dd=2;
			for(i=0;i<TimeCtl;i++)
			{
				Del2ms_DA(1,m1,n1,z1);  //2ms
				if((i%k)==0)	//控制多少时间更新一次数据
					{
					m+=dd;
					n+=dd;
					m1=(int)(Sin128N[m]*(sin));
					n1=(int)(Sin128N[n]*(sin));
					}
				if(m>=64)	 //输出值不能等于64
					{
					break;
					}
			}
			if(BoXing==7)
			{
			for(i=0;i<TimeCtl;i++)
				{
				Del100us(10);
				}
			}
			break;
		default:	//无效
			BoXing = 0x00;
			DianYamax = 0x00;
			WriteTLC5615(512);
			break;
		 }
	} 
	//以下这段代码是解析主机的指令的
	if(RecOK)
		{
 		switch(Buffer[1])	 			//功能号服务程序,读取传感器
			{
			case 0x01:	 			//01号功能,读多线圈
				//DianYamax=DianYamax+Buffer[5];
				Buffer[0]=Add;			//地址
				Buffer[1]=0x01;			//功能号
				Buffer[2]=0x00;	//低八位//0x01;	//字节个数
				Buffer[3]=0x01;//高八位//0x01;	//要返回的数据
				//CRC16(Buffer,4);		//产生前五位的校验码
				CRCParity(Buffer,4);
				Buffer[4]=CRC16L;		//CRC16是低八位在前,高八位在后
				Buffer[5]=CRC16H;
				SendStrCom(Buffer,6); 	//回应上位机
				break;			
			case 0x06:	 				//DA输出的电压值及波形
				TimeCtl = Buffer[3]*100;	//时间单位为ms
				BoXing  = Buffer[4];
				DianYamax = 80+Buffer[5]*10;		//Min[50+5*22=160],Max[50+20*22=490]
				if(Buffer[5]>40)
					DianYamax=480;
				if(BoXing==0)  //如果波形值为0,则说明要停止输出波形
					{
					RunFlag=0;
					WriteTLC5615(512);
					}
				else
					RunFlag=1;
				SendStrCom(Buffer,8);
				break;
			default:  
				break;
			}
		ES		  = 1;
		RecOK	  = 0;
		//RS485_ctl = 0;				//允许接收
		//rs485_num=0;
		//RecStart = 0;
		}
		  
	}
}
//====================================串口接收中断函数 ======================================
void ReceDatCom () interrupt 4 using 3 
{
	unsigned char RecDatNum;	//要接收的数据字节数
	unsigned char ch;
	TI=0;
	RecDatNum = 8;
	if(RI)
		{
		RI=0;
		ch=SBUF;
		if(RecStart)   //已经开始接收数据
			{
			if(RecOK==0)
				{
				Buffer[rs485_num++]=ch;
				if(rs485_num>=RecDatNum)	//一帧接收完成		
					{
					rs485_num=0;
					RecStart = 0;
					CRCParity(Buffer,6); 
					if( (CRC16L==Buffer[6]) && (CRC16H==Buffer[7]) && (Buffer[0]==Add)) //CRC16校验	
						{
						ES = 0;		//接收完八字节有效数据,关串行中断
						RecOK	  = 1;
						//RS485_ctl = 1;//不再接收新数据
						}
					}
				}
			}
		else if((ch==0xEB)&&(RecOK==0))		//字符是0xEB且没有接收完成
			{
			RecStart = 1;
			}
		}
	else
		{
		TI = 0;
		}
	_nop_();
}
/**********************定时中断0服务子程序[]*******************************/
//1.每10Ms一个单位,总长时间可通过外部变量TimerCounter设置(TimerCounter*20)
void TimerCTL(void) interrupt 1   using 2 //计时,精确到10Ms
 	{
		TR0 = 0;
		if(TimeOutS<TimeOutD)
			TimeOutS++;	
		TH0	= 0xC6;				//定时器0,方式1中断,10Ms
		TL0	= 0x66;
		TR0 = 1;
	}


凯特网版权声明:以上内容允许转载,但请注明出处,谢谢!

展开全文READ MORE
STC11F04E信号发生器单片机
谈谈PC机并口操作时序 基于单片机128采样输出的正弦波输程序--查表法

游客 回复需填写必要信息