📄 质谱仪第3版.c
字号:
//新版2.5
#include <reg51.h>
#include <absacc.h>
#include <intrins.h>
#include <IIC.h>
#include <USB.h>
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
sbit AD_STU=P3^5;//AD的状态位
sbit AD_A0=P3^4;//AD的转换信号位
sbit IO_RAM=P1^7;//高电平选择外设,低电平选择RAM
sbit LED_RXD=P3^1;//单片机串口发送指示灯
sbit A16=P1^0;
sbit A17=P1^1;
sbit A18=P1^2;//RAM的最高3位地址
uint RAMadd=0;//RAM的19位地址
uchar Control=0;//全局变量的控制字
uchar rtControl=0;//当前控制字
//'D'-接受设定值的控制
uchar OnTime=0xff;//是否是及时发送,0xff是及时发送,0是储存后发送
uchar Page=0;//读取整幅图的总次数0~255
uint DelayPage=0;//每幅图之间的延时
uchar Segment=0;//每幅图的段数0~255
uint Rate=1;//扫描速度,rate越大,速度越慢
uint PageLength=0;//每幅图的长度
//'C'-采样控制位
uchar PageCount=0;//图幅计数
uchar SegCount=0;//段计数
uchar rtPGA=0;//当前的放大倍数
// 'Z'-温度压强控制
uint Tem_Pre_Point=4096;// 间隔点数
uchar Pre_PGA=0x0;// 压强的放大倍数0
uchar Tem_PGA=0x0;// 温度的放大倍数,高字节温度2,低字节温度1
uint FirstPoint=0;
uint DELAYSEGMENT=255;//段与段之间的延时
uint rtSegPoint=0;//当前的段点位置
uint rtPoint=0;//全幅图点的位置
uint BeginSeg=0,EndSeg=0;//段开始、段结束和放大倍数
uchar PGASeg=0;//段放大倍数
//uint PageAddress=0;//页地址
uint rtRAMPoint=0;//存入RAM时的计数器
//延时(thetime)毫秒
void Delay(uint thetime)
{
uchar j;
while (thetime!=0)
{
thetime--;
for(j=0;j<220;j++){}
}
}
//延时秒
void Delay_s(uint thetime)
{
uchar count;
while(thetime>0)
{
for(count=0;count<10;count++)
{
if(Control=='S')return ;
Delay(100);//延时1秒
}
thetime--;
}
}
// 程控放大器的控制
void PGA(uchar gain)
{
IO_RAM=1;
XBYTE[04]=gain;//写入增益大小
}
// 输出控制
void WriteDAC(uint num)
{
uint high8;
high8=num>>8;
IO_RAM=1;
XBYTE[01]=high8;//写高四位到锁存器
XBYTE[00]=num;//写低八位到锁存器
}
//读取RAM低地址的内容
uchar ReadLowRAM(void)
{
IO_RAM=0;//选中RAM
A16=0;//RAM的最高位为0
return XBYTE[RAMadd];//以字节读取内容
}
//向RAM低地址写入数据
void WriteLowRAM(uchar num)
{
IO_RAM=0;
A16=0;
XBYTE[RAMadd]=num;
}
//读取RAM高地址的内容
uchar ReadHighRAM(void)
{
IO_RAM=0;
A16=1;
return XBYTE[RAMadd];//以字节读取内容
}
//向RAM高地址写入数据
void WriteHighRAM(uchar num)
{
IO_RAM=0;
A16=1;//选中高位
XBYTE[RAMadd]=num;
}
//系统启动时的初始化工作
void InitSystem(void)
{
uint i;uchar dat;
LED_RXD=0;
A17=0;//如果用HY628100就加上这条语句,如果用628400则不用
Delay_s(1);
for(i=0;i<255;i++)
{
dat=IIC_RandomRead(i);
RAMadd=i+0x200;
WriteHighRAM(dat);
}
//读取段与段之间的延时ms
RAMadd=0x200;//先高位
DELAYSEGMENT=ReadHighRAM();
RAMadd=0x201;//后低位
DELAYSEGMENT=(DELAYSEGMENT<<8)|ReadHighRAM();
LED_RXD=1;
Delay(500);
LED_RXD=0;
Delay(500);
LED_RXD=1;
Delay(500);
LED_RXD=0;
Delay(500);
LED_RXD=1;//闪烁3次
}
//接受数据的设置
void SetData(void)
{
uchar count=0;//计输入的段数个数
uchar Seg;//段的控制点,开始,结束,增益
uint PageBeg,PageEnd;//一幅图的开始点,和结束点
Rate=Rec();//扫描速度高8位(1-255);//2
Rate=Rec()|(Rate<<8);//扫描速度(1-65536);//3
OnTime=Rec();//接受是否是及时发送位//4
//if(OnTime!=0)OnTime=0xff;(有主机保证正确)
Page=Rec();//整幅图的总页数0~255//5
//if((Page>15)&&(OnTime==0))Page=0;//不允许超过15图(留给主机判断)
DelayPage=Rec();//每幅图之间的延时//6
DelayPage=Rec()|(DelayPage<<8);//7
Segment=Rec();//每幅图的段数0~255//8
// 温度压强处理
Tem_Pre_Point=Rec()*20;// 压强和温度的监测点间隔
Tem_PGA=Rec();// 温度的放大设置
Pre_PGA=Rec();// 压强的放大设置
for(count=0;count<Segment;count++)
{
Seg=Rec()&0x0f;//段count起始点高8位
RAMadd=count;
if(count==0)PageBeg=Seg;
WriteHighRAM(Seg);//写入RAM的高位
Seg=Rec();//段count起始点低8位
if(count==0)PageBeg=(PageBeg<<8)|Seg;//页的起始点
WriteLowRAM(Seg);//写入RAM的低位
Seg=Rec()&0x0f;//段count结束点高8位
if(count==(Segment-1))PageEnd=Seg;
RAMadd=count+0x100;
WriteHighRAM(Seg);//写入RAM的高位
Seg=Rec();//段count结束点低8位
if(count==(Segment-1))PageEnd=(PageEnd<<8)|Seg;
WriteLowRAM(Seg);//写入RAM的低位
Seg=Rec();//段count增益值
RAMadd=count+0x200;
WriteLowRAM(Seg);//写入RAM的高位
}
// 对压强和温度间隔采样
if(Tem_Pre_Point<20)Tem_Pre_Point=20;
RAMadd=0;
FirstPoint=ReadLowRAM()|(ReadHighRAM()<<8);
PageLength=PageEnd-PageBeg+1;
if(Rec()!='d');//Segment=0;//判断是否正常结束
Sen('F');//回信号起始1
Sen(OnTime);//2
Sen(Page);//3
Sen(DelayPage);//4
Sen(Segment);//5
Sen('f');//回信号表示结束//6
}
// AD 转换
uint AD_Con(void)
{
//IO_RAM=1;
uint dat;
//XBYTE[CS_COV]=0;
//XBYTE[CS_COV]=0;//启动AD转换
while(AD_STU){};//等待AD转换结束
AD_A0=0;//读入高八位
dat=XBYTE[02];
AD_A0=1;//读入低四位
dat=(dat<<4)+XBYTE[02];
return dat;
}
// 读取温度和压强
void Get_Tem_Pre(bit flag)
{
uint data_temp[4];
uchar i;
// 读取温度1
// 设置通道5和放大倍数
PGA((Tem_PGA<<4)|0x01);// 设置放大倍数
Delay(Tem_PGA&0xf);
data_temp[0]=AD_Con();
// 读取压强1
// 设置通道7和放大倍数
PGA((Pre_PGA<<4)|0x03); // 设置放大倍数
Delay(Pre_PGA&0xf);
data_temp[1]=AD_Con();
// 读取温度2
// 设置通道6和放大倍数
PGA((Tem_PGA&0xf0)|0x02);// 设置放大倍数
Delay(Tem_PGA>>4);
data_temp[2]=AD_Con();
// 读取压强2
// 设置通道4和放大倍数
PGA((Pre_PGA&0xf0)|0x04);// 设置放大倍数
Delay(Pre_PGA>>4);
data_temp[3]=AD_Con();
PGA(rtPGA); // 恢复以前的放大倍数
if(flag)// 直接发送
{
Sen('z');
for(i=0;i<4;i++)
{
Sen(data_temp[i]>>8);
Sen(data_temp[i]);
}
}
else
{ // 存入内存
for(i=0;i<4;i++)
{
RAMadd=rtRAMPoint+0x400;//生成存入数PageAddress+据的地址
rtRAMPoint++;//计数存入的地址
//将数据低8位写到低地址
WriteLowRAM(data_temp[i]);
//将数据高8位写到高地址
WriteHighRAM((data_temp[i]>>8)|0xf0);// 标记
//将数据高8位写到高地址
}
}
}
//测试命令
void Test(void)
{
Sen('t');//回信号
///Delay(30);
}
//向EEPROM中写入2402
void Eprom()
{
uchar dat;//数据
uint address1;//地址
address1=Rec();//读地址高8位
address1=Rec()|(address1<<8);//形成16位地址
dat=Rec();//读数据
IIC_RandomWrite(address1&0xff,dat);//写入2402
Sen('p');//回信号
Sen(dat);
RAMadd=address1+0x200;
WriteHighRAM(dat);//回写到RAM中
//读取段与段之间的延时ms
RAMadd=0x200;//先高位
DELAYSEGMENT=ReadHighRAM();
RAMadd=0x201;//后低位
DELAYSEGMENT=(DELAYSEGMENT<<8)|ReadHighRAM();
}
//读EEPROM2402
void ReadE()
{
uchar Low8,datae;
uint High8;
High8=Rec();//EEPROM的高位地址
Low8=Rec();//EEPROM的低位地址
datae=IIC_RandomRead((High8<<8)|Low8);
Sen('W');
Sen(datae);
Sen('w');
}
//终止命令
void Stop()
{
Sen('s');//回信号
PGA(0);//使放大倍数为1
WriteDAC(0);//输出为0
rtControl=0;//当前控制字为零
Control=0;//清控制字为零
PageCount=0;//图幅计数
SegCount=0;//段计数
rtPGA=0;//当前的放大倍数
rtSegPoint=0;//当前的段点位置
rtRAMPoint=0;//RAM的位置为零
rtPoint=0;//全幅图的点
LED_RXD=1;
}
//提供采样过程中的参数变化
void CollectChange(void)
{
RAMadd=SegCount+0x200;
PGASeg=ReadLowRAM();//读取放大倍数
if(PGASeg!=rtPGA)
{
PGA(PGASeg);// 恢复原来的放大倍数
if(!rtPoint)Delay(PGASeg);//延时,确保放大倍数及时设定
rtPGA=PGASeg;
}//若与当前的放大倍数不一样,重新设置
RAMadd=SegCount;
BeginSeg=ReadLowRAM()|(ReadHighRAM()<<8);//一段的起始点
RAMadd=SegCount+0x100;
EndSeg=ReadLowRAM()|(ReadHighRAM()<<8);//一段的结束点
}
//数据采样
void Collect()
{
uint datad1=0; // ad的数据
uint SegOut; // 段与段之间电压输出
uint i; // 扫描速度计数
uint ADCNum=0;//adc的数据
ulong total=0;//ADC的总值
uchar BeginDelay=0;
if(!rtPoint)
{
Sen('c');
CollectChange();
if(BeginSeg!=0)BeginDelay=1;
}
if(PageCount<Page)//该页没有结束
{
if(SegCount<Segment)//该段没有结束
{
rtPoint=rtSegPoint+BeginSeg;//当前点的位置
if(rtPoint<=EndSeg)
{
// DA输出
WriteDAC(rtPoint);
if(BeginDelay)Delay(DELAYSEGMENT);// 起始延时
for(i=0;i<Rate;i++)//与扫描速度有关
{
ADCNum=AD_Con();
if(Rate>1)total=total+ADCNum;
}
if(Rate>1)ADCNum=total/Rate;
if(OnTime)//及时发送
{
Sen('L');//起始标志
Sen((rtPoint>>8)&0xf);//点的位置高8位
Sen(rtPoint);//点的位置低8位&0xff
Sen((ADCNum>>8)&0x0f);//数据的高8位
Sen(ADCNum);//数据的低8位&0xff
// 发送温度和压强
if(((rtPoint-FirstPoint)%Tem_Pre_Point)==10)Get_Tem_Pre(1);
}
else//存入RAM
{
RAMadd=rtRAMPoint+0x400;//生成存入数PageAddress+据的地址
rtRAMPoint++;//计数存入的地址
WriteLowRAM(ADCNum);//将数据低8位写到低地址
WriteHighRAM(ADCNum>>8);//将数据高8位写到高地址
// 存入温度和压强,标志是将高4位置1
if(((rtSegPoint-FirstPoint)%Tem_Pre_Point)==10)Get_Tem_Pre(0);
}
rtSegPoint++;
//LED_AD=1;//关灯
}
else //该段结束
{
rtSegPoint=0;
SegCount++;//段加1
CollectChange();
if(SegCount<Segment)//段和页未结束时
{
RAMadd=SegCount;//段计数地址
SegOut=ReadLowRAM()|(ReadHighRAM()<<8);//获得段的输出值
WriteDAC(SegOut);//段与段之间先输出
//RAMadd=0x200;//段与段之间延时的地址
Delay(DELAYSEGMENT);//ReadHighRAM());//读出段与段之间的延时
}
}
}
else//页结束
{
rtSegPoint=0;
SegCount=0;
CollectChange();
PageCount++;//页加1
WriteDAC(0);//回到第一点
if(OnTime)Sen('n');//一页结束标志符
if((Page-1)){EX0=1;Delay_s(DelayPage);EX0=0;}//页与页之间延时,单位是秒
//AD_COV=1;AD_COV=0;//新的采样
}
}
else Stop();//所有结束采样
}
//读RAM中的内容
void ReadRAM()
{
uint addrlow=0,addrhigh=0;//地址的低位和高位
uint dataRam=0;//数据
uchar page=0;//图号
uint point=0;//点
uchar i;//
page=Rec();//图号,暂时用不到
addrlow=Rec();//接受地址的高8位
addrlow=(addrlow<<8)|Rec();//并成12位的起始地址
addrhigh=Rec();
addrhigh=(addrhigh<<8)|Rec();//并成12位的终止地址
Sen('a');//回信号
point=1;
while(addrlow<=addrhigh)
{
RAMadd=addrlow;
if((ReadHighRAM()&0xf0)==0xf0)// 没有温度和压强,发送一个数据
{
Sen('L');//发送标记
Sen((point>>8)&0xf);//地址的高8位
Sen(point);//地址的低8位
dataRam=ReadHighRAM();
Sen(dataRam&0x0f);//发数据高8位
dataRam=ReadLowRAM();
Sen(dataRam);//发数据低8位
addrlow++;
point++;
}
else// 有数据和压强,发送2个压强和2个温度数据
{
Sen('z');
for(i=0;i<4;i++)
{
RAMadd=addrlow;
dataRam=ReadHighRAM();
Sen(dataRam&0x0f);//发数据高8位
dataRam=ReadLowRAM();
Sen(dataRam);//发数据低8位
addrlow++;
point++;
}
}
}
Sen('n');//图结束标志符
Sen('s');//数据传送结束标志符
}
// 设置温度和压强的放大倍数
void Pre_Tem()
{
// 温度和放大倍数的设置
Tem_PGA=Rec();// 温度的放大,高4位温度1,低4位温度2
Pre_PGA=Rec();// 压强的放大
Get_Tem_Pre(1);// 发送温度压强数据
}
//主程序
void main()
{
WriteDAC(0);//初始化DAC,使之输出为0
PGA(0); //设置放大倍数为1
InitSystem();//系统初始化
InitSerial();//初始化串口通讯
while(1)//主循环
{
switch(Control)
{
//读RAM
case 'A':ReadRAM();Control=0;break;
//读EEPROM
case 'M':ReadE();Control=0;break;
//采样开始命令
case 'C':Collect();break;
//测试命令
case 'T':Test();Control=0;break;
//向EEPROM中写入
case 'E':Eprom();Control=0;break;
//设置采样数据
case 'D':SetData();Control=0;break;
//终止命令
case 'S':Stop();break;
// 压强和温度
case 'Z':Pre_Tem();Control=0;break;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -