📄 c_serialcom.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 + -