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

📄 nmr.c

📁 TLV2544程序
💻 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 + -