?? 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 + -