📄 nmr.c
字号:
/*本程序为核磁共振找水仪下位机程序*/
#include"my.h"
union u {unsigned int word;
struct{unsigned char high;unsigned char low;}bytes;//字节顺序为高位在前的2byte结构
};
union w { ulong dwords;
struct {unsigned int high;unsigned int low;}words;
struct {unsigned char byte3;unsigned char byte2;unsigned char byte1;unsigned char byte0;}bytes;
};
//逻辑
#define FALSE 0
#define TRUE 1
#define H 1
#define L 0
/* 引脚定义*/
// AD:本设计采用TI公司的TLV2544ID,12bit,四通道,200ksps
sbit SDO = P1^0; // TLV2544片选
sbit CS = P1^1; // TLV2544控制模拟输入采样的开始和启动转换
sbit SDI = P1^2; // TLV2544A/D转换结果的三态串行输出端
sbit SCLK = P1^3; // TLV2544串行数据输入
sbit INT = P1^4; // TLV2544串行时钟输入
sbit CSTART = P1^5; // TLV2544转换结束或主处理器中断
// DA:本设计采用TI公司的TLV5636,12bit,单通道
sbit DIN = P0^3; // TLV5636数据输入
sbit DSCLK = P0^4; // TLV5636时钟输入
sbit FS = P0^5; // TLV5636片选
// LED
sbit LEDCLK = P0^0; // LED时钟
sbit LEDDATA = P0^1; // LED数据
sbit LEDCLR = P0^2; // LED清零
//control
sbit powercon = p0^6;
sbit es485 = p1^6;
sbit STATE = P0^7;
sbit trstate = p1^7;
/*协议命令字定义*/
//
#define BEGIN 0x09 //起始码
#define SOH 0x0a //起始码
#define END 0x0d //结束码
//标志号
#define NMRTYPE 'A' //标志号
//设备号
#define EQU 'P' //电源模块标志
//功能码
#define AD 'A' //AD采集
#define DA 'D' //DA输出
#define EC 'E' //设备检测
#define CLOSEDC 'C' //关闭电源逆变器
//返回命令
#define OK 'S' //操作成功
#define ERRBCC 'B'
#define ERRF 'W'
#define ERRC 'C'
// ADC:TLV2544操作命令
#define CHA0 '0'
#define CHA1 '1'
#define CHA2 '2'
#define CHA3 '3'
/*变量定义*/
unsigned char data ch; //ad通道号
unsigned char data mode; //mode 是模式 0为读,1为写 */
unsigned char data n; //数据长度,字节
//ad[chl:各通道采集完成数据;ch:各通道采集过程换算数据]
unsigned int idata chl0,ch0;
unsigned int idata chl1,ch1;
unsigned int idata chl2,ch2;
unsigned int idata chl3,ch3;
bit flag;//电压采集完成标志
bit kk;//校验正确与否标志
unsigned char idata command[20] _at_ 0x48; //串口的发送缓冲区
/*码定义*/
const unsigned char code asci[16]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x41,0x42,0x43,0x44,0x45,0x46};//ASCII
const uchar code ledcode[11]={0xEE,0x28,0xCD,0x6D,0x2B,0x67,0xE7,0x2C,0xEF,0x6F,0xFF};//LED字型
//函数声明
void serial_init(void); //串口初始化
void bcc(void); //校验
void sendcommand(void); //发送命令或返回命令数据
void proc_command(void); //接收命令后处理
unsigned int adx(unsigned char ch); //
void Delay_10_uS(void); //10us延时
unsigned int adrdwr(unsigned int par); //ad读写
void senderrbcc(void); //错误发送
void adinit(void); //ad初始化
void delay_ms(unsigned char i);
void writeda(unsigned int k); //写da,中断调用
void writedam(unsigned int k); //写da,主程序调用
void dainit(void); //da初始化
void LEDinitial(void); //led初始化,检测数码管
void ledout(void); //led显示
void sendequok(void);
void system_init(void);
void close(void);
void main(void)
{
unsigned int idata command1,command2;
unsigned char data i,j;
SP=0x60;
system_init();
serial_init();
adinit();
dainit();
LEDinitial();
flag=1; //未采集完成,禁止上位机读取ad数据
while(1)
{
//
STATE=~STATE;
for (j=0;j<5;j++){//一个显示过程
ch0=0x0000;
for(i=0;i<16;i++)//一个采集过程
{
command1=0x0000;
command2=adrdwr(command1);
while(INT==1);
CS=H;
delay_ms(1);
command2=adrdwr(command1);
while(INT==1);
CS=H;
command2=command2>>4;
ch0=ch0+command2;
}
//
ch1=0x00;
for(i=0;i<16;i++)
{
command1=0x2000;
command2=adrdwr(command1);
while(INT==1);
CS=H;
delay_ms(1);
command2=adrdwr(command1);
while(INT==1);
CS=H;
command2=command2>>4;
ch1=ch1+command2;
}
//
ch2=0x00;
for(i=0;i<16;i++)
{
command1=0x4000;
command2=adrdwr(command1);
while(INT==1);
CS=H;
delay_ms(1);
command2=adrdwr(command1);
while(INT==1);
CS=H;
command2=command2>>4;
ch2=ch2+command2;
}
///
ch3=0x00;
for(i=0;i<16;i++)
{
command1=0x6000;
command2=adrdwr(command1);
while(INT==1);
CS=H;
delay_ms(1);
command2=adrdwr(command1);
while(INT==1);
CS=H;
command2=command2>>4;
ch3=ch3+command2;
}
flag=1;
chl0=ch0;
chl1=ch1;
chl2=ch2;
chl3=ch3;
flag=0;
}
ledout();//显示通道1和2电压
}
}
void system_init(void)
{
powercon = H;
es485=L;
STATE=L;
trstate=H;
}
//led初始化子函数,点亮全部数码管及其各码段
void LEDinitial(void)
{
unsigned char data k,i,wordC;
LEDCLR=0;
LEDCLR=1;
LEDCLK=1;
for(k=0;k<6;k++)
{
wordC=ledcode[10];
for(i=0;i<8;i++){
LEDCLK=0;
Delay_10_uS();
if ((wordC&0x80)==0x80) LEDDATA=1;
else LEDDATA=0;
wordC=wordC<<1;
LEDCLK=1;
Delay_10_uS();
}
}
delay_ms(500);
}
void close(void) using 1
{
powercon=H;
command[0]=SOH;
command[1]=NMRTYPE;
command[2]=EQU;
command[4]=OK;
command[7]=END;
mode=1;n=8;
bcc();
sendcommand();
}
//led显示,左数码管显示通道1,右数码管显示通道2;
void ledout(void) using 1
{
unsigned long idata V1;
unsigned char data tmp,i,j,k,wordC,ledword[6];
LEDCLR=0;
LEDCLR=1;
LEDCLK=1;
V1=chl0;
V1=V1>>4;
tmp=V1/1000;
ledword[0]=tmp&0x0f;
V1=V1-tmp*1000;
tmp=V1/100;
ledword[1]=tmp&0x0f;
V1=V1-tmp*100;
tmp=V1/10;
ledword[2]=tmp&0x0f;
//
V1=chl1;
V1=V1>>4;
tmp=V1/1000;
ledword[3]=tmp&0x0f;
V1=V1-tmp*1000;
tmp=V1/100;
ledword[4]=tmp&0x0f;
V1=V1-tmp*100;
tmp=V1/10;
ledword[5]=tmp&0x0f;
for(i=0;i<6;i++)//依次显示六个数码管
{
k=ledword[5-i];
wordC=ledcode[k];
for(j=0;j<8;j++){//依次发送各数码管码段
LEDCLK=0;
if ((wordC&0x80)==0x80) LEDDATA=1;
else LEDDATA=0;
wordC=wordC<<1;
LEDCLK=1;
Delay_10_uS();
}
}
}
void Delay_10_uS(void) using 1
{
unsigned char data i=10;
while(i--);
}
void delay_ms(unsigned char ms_number)
{
unsigned int idata i;
unsigned char data j;
for(j=0;j<ms_number;j++)
for(i=0;i<229;i++);
}
/*********************************************/
//向上位机发送数据
void sendcommand(void) using 1
{
unsigned char data j=0;
unsigned char data tmp=0;
es485 =H;
trstate=L;
TH0=0xa0; TL0=0x00; TF0=0;
TR0=1;
while(TF0==0) { }
tmp=command[j];
TI=0;
while(tmp!=0x0d)
{
tmp=command[j];
SBUF=tmp;
j=j+1;
while(!TI);
TI=0;
}
//
es485 =L;
trstate=H;
TH0=0xa0; TL0=0x00; TF0=0;
TR0=1;
while(TF0==0) { }
//
}
/*********************************************/
//串口初始化:晶振采用22。1184M,波特率38400,方式一
void serial_init()
{
SCON=0x50; TMOD=0x21; PCON=0x80; TR0=0; 0;
TH1=0xff; TL1=0xff; TR1=1; ET0=0; ES=1; EA=1;
es485=L;
}
void serial(void) interrupt 4 using 1
{
unsigned char data temp,j;
ES=0;
j=0;
RI=0;
temp=SBUF;
trstate=L;
if(temp==BEGIN)
{
command[j]=temp;
j=j+1;
while((j<20)&(temp!=0x0d))
{
while(!RI);
RI=0;
temp=SBUF;
command[j]=temp;
j=j+1;
}
mode=0;n=j;
bcc();
if(kk){
proc_command();
}
else{
senderrbcc();
}
}
ES=1;
trstate=H;
}
//数据传送错误返回指令
void senderrbcc(void) using 1
{
command[0]=SOH;
command[1]=NMRTYPE;
command[2]=EQU;
//
command[7]=END;
command[4]=ERRBCC;
mode=1;n=8;
bcc();
sendcommand();
}
//AD写配置寄存器及控制通道,并读取数据
unsigned int adrdwr(unsigned int par)
{
unsigned char data i;
unsigned int idata parp,parp1;
parp=par;
parp1=0x00;
SCLK=L;
CS=H;
Delay_10_uS();
CS=L;
for(i=0;i<16;i++)
{
if((parp&0x8000)==0x8000) {SDI=H;}else {SDI=L;}
parp=parp<<1;
SCLK=H;
Delay_10_uS();
parp1=parp1<<1;
if(SDO==H){parp1=parp1|0x0001;}
SCLK=L;
Delay_10_uS();
}
Delay_10_uS();
CS=H;
return (parp1);
}
//写da,中断调用
void writeda(unsigned int k) using 1
{
unsigned char data i;
unsigned int idata dat;
dat=k;
FS=L;
Delay_10_uS();
for(i=0;i<16;i++)
{
DSCLK=H;
Delay_10_uS();
if((dat&0x8000)==0x8000)DIN=H;else DIN=L;
dat=dat<<1;
DSCLK=L;
Delay_10_uS();
}
FS=H;
}
//da初始化
void dainit(void) using 1
{
DSCLK=L;
DIN=H;
FS=H;
//writeda(0xd002);//内部参考
writeda(0xd000);
}
//ad初始化
void adinit(void)
{
unsigned int idata command1;
CS=H;
SCLK=L;
CSTART=H;
SDI=H;
SDO=H;
INT=H;
command1=0xA000; //power up
command1=adrdwr(command1);
delay_ms(10);
command1=0xA000;
command1=adrdwr(command1);
delay_ms(10);
}
//ad发送数据
void sendadc(void) using 1
{
union u idata kk;
unsigned char data k,m;
while(flag==1);
switch(ch){
case '0': kk.word=chl0;
break;
case '1': kk.word=chl1;
break;
case '2': kk.word=chl2;
break;
case '3': kk.word=chl3;
break;
default: kk.word=chl0;
break;
}
command[0]=SOH;
command[1]=NMRTYPE; //type号
command[2]=EQU; //设备号
//command[3]:功能码[A];command[4]:通道号
command[5]= OK; //确认命令,选择通道正确,并返回数据
command[11]=END;
k=kk.bytes.high;
m=k;
k=k>>4;
k=k&0x0f;
command[6]=asci[k];
k=m;
k=k&0x0f;
command[7]=asci[k];
k=kk.bytes.low;
m=k;
k=k>>4;
k=k&0x0f;
command[8]=asci[k];
k=m;
k=k&0x0f;
command[9]=asci[k];
mode=1;n=12;
bcc();
sendcommand();
}
//校验
void bcc(void) using 1
{
unsigned char data jj,jj1;
unsigned char idata bcc1,bcc2;
kk=0;
if (mode==0x0)
{
bcc1=0;
for(jj=0;jj<n-3;jj++)
{
bcc1=bcc1^command[jj];
}
jj1=bcc1&0x0f;
bcc2=asci[jj1];
bcc1=bcc1>>4;
jj1=bcc1&0x0f;
bcc1=asci[jj1];
if(bcc1==command[jj]&(bcc2==command[jj+1]))
{
kk=1;
}
else
{
kk=0;
}
}
else
{
bcc1=0;
for(jj=0;jj<n-3;jj++)
{
bcc1=bcc1^command[jj];
}
bcc2=asci[bcc1&0x0f];
jj=jj+1;
command[jj]=bcc2;
bcc1=asci[(bcc1&0xf0)>>4];
jj=jj-1;
command[jj]=bcc1;
kk=1;
}
}
//功能码错误返回子程序
void senderrf(void) using 1
{
command[0]=SOH;
command[1]=NMRTYPE;
command[2]=EQU;
command[4]=command[3];
command[3]=ERRF;
command[7]=END;
mode=1;n=8;
bcc();
sendcommand();
}
//通道选择错误返回子程序
void senderrc(void) using 1
{
command[0]=SOH;
command[1]=NMRTYPE;
command[2]=EQU;
//command[3]:功能码[A];command[4]:通道号
command[5]=ERRC; //错误命令,选择通道不正确,返回通道号
command[8]=END;
mode=1;n=9;
bcc();
sendcommand();
}
//da输出
void daout(void) using 1
{
unsigned char data h,m,l;
union u idata kk;
unsigned int idata dat;
h=command[4];
m=command[5];
l=command[6];
if(h<0x41){h=h-0x30;}else{h=h-0x41+0xa;}
if(m<0x41){m=m-0x30;}else{m=m-0x41+0xa;}
if(l<0x41){l=l-0x30;}else{l=l-0x41+0xa;}
h=h&0x0f;
h=h|0x40;
m=m&0x0f;m=m<<4;
l=l&0x0f;m=m|l;
kk.bytes.high=h;
kk.bytes.low=m;
dat=kk.word;
writeda(dat);
writeda(dat);
powercon=L;
//
command[0]=SOH;
command[1]=NMRTYPE;
command[2]=EQU;
command[7]=command[6]; //DH
command[6]=command[5]; //DM
command[5]=command[4]; //DL
command[4]=OK; //成功标志位:S
//
command[10]=END;
mode=1;n=11;
bcc();
sendcommand();
}
void sendequok(void) using 1
{
command[0]=SOH;
command[1]=NMRTYPE;
command[2]=EQU;
command[4]=OK;
command[7]=END;
mode=1;n=8;
bcc();
sendcommand();
}
//主处理程序
void proc_command() using 1
{
if (command[1]==NMRTYPE &command[2]==EQU){//电源模块
switch(command[3]){
case AD://ad
switch(command[4]){
case CHA0 :
ch='0';sendadc();break;
case CHA1 :
ch='1';sendadc();break;
case CHA2 :
ch='2';sendadc();break;
case CHA3 :
ch='3';sendadc();break;
default:senderrc();break;//通道错误返回
}
break;
case DA://da
daout();
break;
case EC://设备检测
sendequok();
break;
case CLOSEDC://关闭高压电源,再次调整电压时,系统自动开启该模块!软件需先写0电压值,在调用此函数!
close();
break;
default:senderrf();//功能码错误返回
break;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -