基于STC11F04E单片机的信号发生器之程序设计
前机有文章已经提到过硬件电路的设计了,这里主要描述程序的设计,以下代码就是信号发生器的主体代码,其他的程序函数因与其他文章重复,故不再贴出。
/****************************************************************************** 单片机: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; }
凯特网版权声明:以上内容允许转载,但请注明出处,谢谢!