⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 c_serialcom.c

📁 51单片机产生三角波,正弦波,方波,并通过串口从上位机发送命令改变波形幅值等
💻 C
字号:
#include<reg52.h>
#include<math.h>
#include"define.h"

#define XBYTE ((volatile unsigned char xdata*)0)
#define PI 3.14

unsigned  char    *Promopt="The AD Channel now:  \n  ";
unsigned  char     RecvData=0;//保存通过串口接收到的命令字
uint ADVALUE=0;	//保存AD转换的值
int WhichCh=0;	//当前采样的通道号
int ConverSemp=0;	//AD转换信号灯:
					//AD转换时值为1;
					//AD转换完毕时值为2;
					//转换值被程序用过时,值为0;
int RecvSign=False;	//串口数据标志,有新数据时为True;数据被用之后为False.
uint RATE=10;		//串口发送数据的速率
uint FUZHI=10;		//各种波形的幅值控制
uint MODE=0;		//波形的模式控制

void initial(void);
void Send (unsigned char*temp,int i);
uint Get (void);
void lightshow(void);
void delay(int i);
void SendTrigular(uint mode,uint rate,uint fuzhi);
void SendSquare(uint length,uint rate,uint heigh);
void SendSin(uint rate,uint fuzhi);
uint GetADValue(int Channel);
void SendADValue(int Channel,uint rate);
void ChangeSemp(int Semp);
HANDLE HandleCommand(void);
void HandleA(void);
void HandleB(void);
void HandleC(void);
void HandleF(void);
void HandleG(void);
void HandleH(void);
void HandleK(void);
void HandleL(void);
void HandleM(void);
//命令处理函数数组
HANDLE Handle[]={HandleA,HandleB,HandleC,0,0,HandleF,HandleG,HandleH,0,0,HandleK,HandleL,HandleM};

void initial(void)
{
  IP=0x10;	//将串行口中断设为高级中断,其他为低级中断
  IE=0x94;	//
  TH1=0xf3;
  TL1=0xf3;
  SCON=0xd0;
  TMOD=0x21;
  TCON=0x05;
  TR1=1;  
  P0=0xff;
  P1=0xff;
  P2=0xff;
}

void main(void)
{
  int Channel=2;
  HANDLE h;
  initial();		//初始化硬件
  lightshow();
  P0=0xaa;
  while(1)
  {
  	h=HandleCommand();
	h();
  }
}

//处理输入的命令值
//从RecvData中读入命令字,根据约定,返回对应的处理函数
HANDLE HandleCommand(void)
{
	int CommNO=0;//保存命令编号
	//初始功能(即静态变量)均定义为A,
	static HANDLE hCommand=HandleA;
	//当修改速率或幅值这些参数时,将原先的命令缓存在hPreCommand中
	static HANDLE hPreCommand=HandleA;
	//如果前一个命令是修改参数,就将命令改为缓存在hPreCommand的功能,防止不断进入修改
	if(hCommand==HandleK||hCommand==HandleL||hCommand==HandleM)hCommand=hPreCommand;
	if(RecvSign==False)return hCommand;//没有收到数据,直接返回。
	if(!((RecvData>='A'&&RecvData<='M')&&((RecvData-'A'+1)%5<4)))return hCommand;//输入命令出错,不做处理
	//如果命令是修改参数的命令,就将当前命令缓存,以便后边恢复
	if(RecvData>='K'&&RecvData<='M')hPreCommand=hCommand;
	CommNO=RecvData-'A';
	hCommand=Handle[CommNO];
	RecvSign=False;//处理完数据,将标志重新赋为False
	return hCommand;
}
//处理命令A:产生三角波
void HandleA(void)
{
	SendTrigular(MODE,RATE,FUZHI);
}
//处理命令B:产生正弦波
void HandleB(void)
{
	SendSin(RATE,FUZHI);
}
//处理命令C:产生方波
void HandleC(void)
{
	SendSquare(10,RATE,FUZHI);
}
//处理命令F:读取AD通道0
void HandleF(void)
{
	SendADValue(0,RATE);
}
//处理命令G:读取AD通道1
void HandleG(void)
{
	SendADValue(1,RATE);
}
//处理命令H:读取AD通道2
void HandleH(void)
{
	SendADValue(2,RATE);
}
//处理命令E:改变发送速率RATE
void HandleK(void)
{
	uint t;
	t=Get();
	if(t<'0'||t>'9'){HandleK();return;}//命令出错,作递归调用
	RATE=t-'0';
}
//改变波形幅值
void HandleL(void)
{
	uint t;
	t=Get();
	if(t<'0'||t>'9'){HandleL();return;}//命令出错,作递归调用
	FUZHI=(t-'0')*25;
}
//改变三角波的模式
void HandleM(void)
{
	uint t;
	t=Get();
	if(t<'0'||t>'2'){HandleM();return;}//命令出错,作递归调用
	MODE=t-'0';
}

//AD转换中断处理
//AD转换完毕后触发,执行完毕后,结果放在全局变量ADVALUE中,并且改变ConverSemp为2
void GetADValueInt(void) interrupt 2
{
	int addr=0x7FF8;
	P0_0=~P0_0;
	if(ConverSemp==2)return;//上次转换值仍没有被读取,直接返回
	ChangeSemp(1);	//信号灯为1,表示正在AD转换
	addr+=WhichCh;
	ADVALUE=XBYTE[addr];
	ChangeSemp(2);	//信号灯为2,表示转换完毕
	EA=True;
}

//串口接受中断
//接受到的数据放在RecvData变量中
void  Receive_Int(void) interrupt 4
{
	EA=False;
	if (RI==1)
	{
	   ACC=SBUF;
	   RecvData=ACC;
	   RecvSign=True;	//数据标志为赋为True;
	}
	RI=0;
	EA=True;
}

//串口发送Channel指示的AD通道值,速率为rate
//Channel=0时取亮度值
//Channel=1时取温度值
//Channel=2时取A/D2
void SendADValue(int Channel,uint rate)
{
	uint value=0;
	value=GetADValue(Channel);
	Send(&value,1);
	delay(rate);
}

//该函数获取Channel通道的值
//Channel=0时取亮度值
//Channel=1时取温度值
//Channel=2时取A/D2
uint GetADValue(int Channel)
{
	int addr=0x7FF8;
	addr+=Channel;
	XBYTE[addr]=0;	//启动AD转换
	while(ConverSemp!=2);//等待AD转换完毕
	ChangeSemp(0);		//因为取了AD转换结果,信号灯赋为0
	return ADVALUE;
}

//改变信号灯的值,关键点是开关总中断,以免修改过程受到干扰
void ChangeSemp(int Semp)
{
	EA=False;
	ConverSemp=Semp;
	EA=True;
}

//从串口读入一个字符
uint Get(void)
{
	while(RecvSign==False);//等待串口读入数据
	RecvSign=False;	//即将读数据,标志位赋为False
	Send(&RecvData,1);
	return RecvData;		//因为中断将数据放入RecvData,所以直接返回即可
}

//往串口发送j个数据
void Send(unsigned char *temp,int count)
{
  int i=0;
  EA=False;
  for (i=0;i<=count-1;i++)
  {
	   ACC=temp[i];
	   SBUF=ACC;
	   while(TI==0);
	   TI=0;
  }
  EA=True;
}

//发送三角波,
//参数mode为波形方式:0,为左三角波,1为右三角波,2为左右对称的三角波
//Rate控制发送速率。
void SendTrigular(uint mode,uint rate,uint fuzhi)
{
	uint i=0;
	if(mode==0||mode==2)
	{
		for(i=0;i<=fuzhi;i++)
		{
			Send(&i,1);
			delay(rate);
		}
	}
	if(mode==1||mode==2)
	{
		for(i=fuzhi;i>0;i--)
		{
			Send(&i,1);
			delay(rate);
		}
	}
}

void SendSquare(uint length,uint rate,uint heigh)
{
	uint dForSend=0,i=0;
	for(i=length;i!=0;i--)
	{
		Send(&dForSend,1);//输出length次的低电平
		delay(rate);
	}
	dForSend=heigh;
	for(i=length;i!=0;i--)
	{
		Send(&dForSend,1);//输出length次的高电平
		delay(rate);
	}
}

void SendSin(uint rate,uint fuzhi)
{
	float inSin=0;
	uint outSin=0;
	for(;inSin<2*PI;inSin+=0.2)
	{
		outSin=(sin(inSin)+1.0)*(fuzhi/2);
		Send(&outSin,1);
		delay(rate);
	}
}

void delay(int  i)
{
   int a;
   while (i--!=0)
   {
      a=0x0fa;
      while(a--!=0);
   }  
}

void lightshow(void)
{
  int SDelayValue=10;
  unsigned char n;
  unsigned int i,j;
  for(j=0;j<2;j++)
  {
    n=1;  			//从右至左逐个灯亮
    P0=~n;
    delay(SDelayValue);
    for(i=0;i<7;i++)
    {
      n*=2;
      P0=~n;
      delay(SDelayValue);
    }
  }
  n=0xff;		 //从右至左递增灯亮
  for(i=0;i<8;i++)
  {
    n*=2;
    P0=n;
    delay(SDelayValue);
  }

  n=0xff;	   //	 从右至左递增灯灭
  for(i=0;i<8;i++)
  {
    n*=2;
    P0=~n;
    delay(SDelayValue);
  }

  for(i=0;i<8;i++) // 灯全亮全灭四次
  {    
    P0=~P0;
    delay(SDelayValue);
  }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -