📄 spr_ri080526.c
字号:
//08.3.17:定时测量改为由上位机定时下发单次测量的形式
//08.3.26:修改了中断服务程序
//08.4.8:定时测量模块由上位机进行控制,下位机删除定时测量模块
//08.4.8:增加实时响应,即每完毕单次测量或连续测量等等的测量命令需给上位机发送结束帧
//08.4.8:增加终止命令
//08.4.22修改继续接受命令子程序 Con_receive(),接收命令采用UART0中断方式,增加UART()中断程序
//08.4.24增加单次采样模块,使得和上位机匹配完成初始化,命令分析程序commend_analys()稍作修改
//08.4.26增加调试测量模块
//08.5.26上电在继续接收命令时采用中断方式,并让SPR不停工作,解决首段曲线不好的问题,不存在毛刺问题,所以中间不改动
//////////////////////////////////////////////////////////////////////////////////////////////
#include "c8051f020.h"
#include "ABSACC.H"
#include "INTRINS.H"
#define local_add 0x01 //
#define version 0x01 //SPR仪器版本号
#define rebuf_max 40 //接收缓冲区大小
#define ansbuf_max 15 //发送缓冲区大小
//测量结果存放区首地址
#define XBKaddr 0x0700 //全暗背景Ib
#define XAIRaddr 0x0880 //空气背景Ia-Ib
#define XSIGaddr 0x0A00 //单次测量信号Sa-Sb
#define XORGaddr 0x0B80 //原始信号Sa
#define XOPTaddr 0x0D00 //最优化计算值的存放区
//最优化结果存放区
#define XPLESH XBYTE[0x0680] //存放象素大小,两字节
#define XPLESL XBYTE[0x0681]
#define XBRIGHT XBYTE[0x0682] //存放LED亮度等级,一字节
#define XTIME XBYTE[0x0683] //存放积分时间,一字节
#define XCOUNT XBYTE[0x0684] //存放平均测量次数,一字节
#define XVOLTH XBYTE[0x0685] //存放最优化后平均电压,两字节
#define XVOLTL XBYTE[0x0686]
#define HIGH 1
#define LOW 0
//最优化中间电压的设定
#define MIDLL 2966 //相当于电压2.2V
#define MIDL 3236 //相当于电压2.4V
#define MID 3370 //相当于电压2.5V
#define MIDH 3505 //相当于电压2.6V
#define MIDHH 3775 //相当于电压2.8V
#define FULL 4095 //相当于电压3.0375V,AD满量程
//////////////////////////////////////////////////////////////////////////////////////////////
//函数申明
//////////////////////////////////////////////////////////////////////////////////////////////
void Reset_Sources_Init(void);
void Oscillator_Init(void);
void Port_IO_Init(void);
void UART_Init(void);
void Timer_Init(void);
void Voltage_Reference_Init(void);
void ADC_Init(void);
void PCA_Init(void);
void Init_Device(void);
void commend_analys(void);
void senderror(void);
void SendResponse(void);
void sendsignal(unsigned char port, unsigned int VL, unsigned int VH, unsigned int TL,unsigned int TH,unsigned int status);
void CheckVersion(void);
void BeginOptim(void);
void OptimResult(void);
void OptimSet(void);
void BeginSingle(void);
void Con_receive(unsigned int n);
void BeginBkdark(void);
void single_measure(unsigned int V1,unsigned int T1,unsigned int V2,unsigned int T2,unsigned int V3,unsigned int T3);
void continue_measure(unsigned int V1,unsigned int T1,unsigned int V2,unsigned int T2,unsigned int V3,unsigned int T3);
void wateradjust_measure(unsigned int V1);
void sampleadjust_measure(unsigned int V2);
void clean(unsigned int V3,unsigned int T3);
void Measure(unsigned int add);
void Sub(unsigned int addr1, unsigned int addr2, unsigned int addr3);
void UploadData(unsigned int addr);
void Valve_Switch(unsigned int port);
void FlashWrite();
void delay(unsigned int n);
//////////////////////////////////////////////////////////////////////////////////////////////
//全局变量
//////////////////////////////////////////////////////////////////////////////////////////////
static idata unsigned char rebuf[rebuf_max];
static idata unsigned char ansbuf[ansbuf_max];
static idata unsigned char Uart1Tbuf[ansbuf_max];
//static data signed int GapTime_R=0;
//static idata unsigned int SetTime_R=0;
static unsigned int data InwaterTime_R=0; //设置各步操作所需的时间
static unsigned int data InsampleTime_R=0;
static unsigned int data CleanTime_R=0;
static unsigned int data Num50ms_R=0;
static unsigned int data Num1s_R=0;
unsigned int data uartrecnum = 0;
//bit WorkFlag;
//bit TimingIni_F;
//bit SetTime_F;
bit InwaterTime_F;
bit InsampleTime_F;
bit CleanTime_F;
unsigned int data xples; //像素大小
unsigned char data bright; //LED亮度
unsigned char data time; //积分时间
unsigned char data count; //平均测量次数
bit time_flag; //积分时间标志位
bit tenmillisec_flag;
bit optim_flag; //最优化标志位
sbit S_START = P3^4;
sbit S_CLOCK = P3^5;
sbit SNSS = P3^7;
sbit DIR = P2^2;
sbit FREE = P2^3;
sbit CP = P1^2;
void main()
{
unsigned char data i;
unsigned char code * pread;
Init_Device();
Num50ms_R=0;
Num1s_R=0;
//WorkFlag=0; //清除各类标志
//TimingIni_F=0;
//SetTime_F=0;
InwaterTime_F=0;
InsampleTime_F=0;
CleanTime_F=0;
TR2=0; //关闭定时器
pread = ( unsigned char code * ) 0x00;//读外部FLASH中的值
PSCTL |= 0x04; //打开flash
XPLESH = *pread++; //++ 的优先级大于*
XPLESL = *pread++;
XBRIGHT = *pread++;
XTIME = *pread++;
XCOUNT = *pread++;
XVOLTH = *pread++;
XVOLTL = *pread++;
PSCTL &= ~0x04; //关闭flash
EA = 1; //中断总允许
while(1)
{
for (i=0;i<rebuf_max;i++) //清除接收缓存区
rebuf[i]=0x00;
// delay(20);
commend_analys();
}
}
//////////////////////////////////////////////////////////////////////////////////////////////
//初始化函数
//功能:初始化上位机母串口0波特率为38400BPS(采用TIMER 2),子串口0波特率为:9600;
// 子串口1波特率为:9600;子串口2波特率为:9600;初始化上位机母串口1波特率为57600BPS(采用TIMER 1)
//串口0用于上下位机的通信
// 输入:无
// 输出:无
//////////////////////////////////////////////////////////////////////////////////////////////
void Reset_Sources_Init() //禁止看门狗
{
WDTCN = 0xDE;
WDTCN = 0xAD;
}
void Oscillator_Init()
{
unsigned int data i = 0;
OSCXCN = 0x67;
for (i = 0; i < 3000; i++); // Wait 1ms for initialization
while ((OSCXCN & 0x80) == 0);
OSCICN = 0x08;
}
void Port_IO_Init()
{
XBR0 = 0x0F; //使PCA的CEX0,UART0,SPI0,SMBus0连接到I/O口,并将UART0,SPI0,UART1的端口引脚设为推挽方式
XBR2 = 0xC4; //UART1连接到I/O口,禁止弱上拉,允许交叉开关
P0MDOUT = 0x15; //推挽方式:P0.0(UART0_TX0),P0.2(SPI_SCK),P0.4(SPI_MOSI);漏极开路:P0.1(UART0_RX0),P0.3(SPI_MISO),P0.5(SPI_NSS),P0.6-P0.7(SMBus)
P1MDOUT = 0xFD; //推挽方式:P1.0(UART1_TX1),P1.2(CEX0),P1.3-P1.7(未用I/O口);漏极开路:P1.1(UART1_RX1)
P2MDOUT = 0xFF; //推挽方式:P2.0-P2.7(未用I/O口)
P3MDOUT = 0xCF; //推挽方式:P3.0-P3.3(未用I/O口),P3.6(未用I/O口),P3.7(SNSS);漏极开路:P3.4-P3.5(S_START,S_CLOCK)
P74OUT = 0xFF; //推挽方式:P4-P7(未用I/O口)
P0 = 0xFF; //对于数字输入引脚,将其配置为漏极开路,并向端口数据寄存器写1
P1 = 0xFF; //对于输出引脚,无论是推挽还是漏极开路,都向其端口寄存器写1
P3 = 0x40; //开始时LED关闭,SPI从机选择位为低电平
}
void UART_Init()
{
PCON |= 0x80; //UART0波特率加倍
SCON0 = 0x50; //UART0工作在方式1,UART0接收允许,TI0,RI0清零
SCON1 = 0x50; //UART1工作在方式1,UART1接收允许,TI1,RI1清零
SCON0 &= 0xFC; //将TI0和RI0清0
// SCON1 &= 0xFC; //将TI0和RI0清0
}
void Timer_Init()
{
CKCON = 0x10; //T1采用系统时钟,不分频,T0用作传感器内部积分时间,T0/T2/T4采用系统时钟的12分频
TR1 = 0; //关闭定时器
TMOD = 0x20; //T1为8位自动重装载模式
TH1 = 0xF4; //T1溢出作为UART0的收发时钟,和上位机通信,加倍后波特率57600
TR1 = 1; //启动定时器
T4CON = 0x30; //T4溢出作为UART1的收发时钟,和阀通信
RCAP4L = 0xDC; //波特率9600
RCAP4H = 0xFF;
T4CON |= 0x04; //启动定时器
IE = 0xA2; //中断总允许,允许T2,T0中断,屏蔽T1中断
T2CON = 0x00; //T2用作50ms16位自动重装载定时器功能
TL2= 0x00;
TH2= 0x4C;
RCAP2L = 0x00; //存放定时50ms的初值
RCAP2H = 0x4C;
TMR3CN = 0x00;
TMR3RLL = 0x00;
TMR3RLH = 0x4c;
TMR3L = 0x00;
TMR3H = 0x4c;
}
void Voltage_Reference_Init()
{
REF0CN = 0x07; //内部偏压发生器、内部电压基准缓冲器、内部温度传感器工作,ADC0电压基准取自VREF0
}
void ADC_Init()
{
AMX0SL = 0x00;
ADC0CF = 0x28;
ADC0CN = 0x80;
}
void PCA_Init() //功能:步进电机转速初始化
{
PCA0CN=0x00; //不允许CFF0中断
PCA0MD=0x00; //PCA中断不允许,选择系统时钟12分频(系统时钟4分频02H)作为PCA输入
PCA0CPM0=0x46; //采用频率输出方式
PCA0CPL0=0x00;
// PCA0CPH0=0xff; //存放输出电平改变前要计的PCA时钟数
PCA0L=0x00; //PCA计数器低字节存放初值
PCA0H=0x00; //PCA计数器高字节无用
CR=0;
FREE = 0; //经过反向器后,FREE、DIR均为高电平
DIR = 0;
}
void Init_Device(void)
{
Reset_Sources_Init();
Oscillator_Init();
Port_IO_Init();
UART_Init();
Timer_Init();
Voltage_Reference_Init();
ADC_Init();
PCA_Init();
}
///////////////////////////////////////////////////////////////////////////////////////////////
//发送错误帧函数
//使用全局变量:REBUF[]
//入口条件:无
//出口条件:无
//功能:发送错误帧给上位机
///////////////////////////////////////////////////////////////////////////////////////////////
void senderror(void)
{
unsigned char i=0;
ansbuf[0]=0x01;
ansbuf[1]=0x55;
ansbuf[2]=0xff;
ansbuf[3]=0xff;
ansbuf[4]=0xff;
ansbuf[5]=0xff;
ansbuf[6]=0x57; //错误帧检验码
for (i=0;i<7;i++) //发送错误帧
{
TI0 = 0;
SBUF0 = ansbuf[i];
while(TI0 == 0) ;
}
}
///////////////////////////////////////////////////////////////////////////////////////////////
//发送响应函数
//使用全局变量:ansbuf[]
//功能:从机响应命令后发送响应帧给上位机
///////////////////////////////////////////////////////////////////////////////////////////////
void SendResponse(void)
{
unsigned char data check = 0;
unsigned char data i;
for(i=0; i<6; i++)
{
check = check ^ rebuf[i]; //计算正确的校验位
SCON0 &= 0xfd;
SBUF0 = rebuf[i];
while(TI0 == 0);
}
TI0 = 0;
SBUF0 = check;
while(TI0 == 0);
}
///////////////////////////////////////////////////////////////////////////////////////////////
//发送状态信号函数
//使用全局变量:REBUF[]
//入口条件:无
//出口条件:无
//功能:发送状态信号给主板
///////////////////////////////////////////////////////////////////////////////////////////////
void sendsignal(unsigned char port, unsigned int VL, unsigned int VH, unsigned int TL,unsigned int TH,unsigned int status)
{
unsigned char i=0,check=0,temp;
ansbuf[0]=0x02;
ansbuf[1]=0x12;
ansbuf[2]=0x00;
ansbuf[3]=0x16;
ansbuf[4]=port;
ansbuf[5]=VL;
ansbuf[6]=VH;
ansbuf[7]=TL;
ansbuf[8]=TH;
ansbuf[9]=status;
ansbuf[10]=0x00;
ansbuf[11]=0x00;
ansbuf[12]=0x00;
ansbuf[13]=0x00;
for (i=0;i<14;i++)
{
check=check^ansbuf[i];
}
ansbuf[14]=check;
for (i=0;i<15;i++) //发送正确帧
{
SCON0 &= 0xfd;
SBUF0 = ansbuf[i];
temp = SCON0; //将SCON0的值赋给temp
temp &= 0x02; //屏蔽除TI1位以外的所有位
while(temp == 0) //查询是否发送完毕
{
temp = SCON0;
temp &= 0x02;
}
}
}
///////////////////////////////////////////////////////////////////////////////////////////////
//查询版本号
//功能:
///////////////////////////////////////////////////////////////////////////////////////////////
void CheckVersion(void)
{
unsigned char data j;
unsigned char data check = 0;
ansbuf[0] = 0x01;
ansbuf[1] = 0x03;
ansbuf[2] = 0x00;
ansbuf[3] = 0x02;
ansbuf[4] = 0x00;
ansbuf[5] = version; //版本号01
for (j=0; j<6; j++)
{
check = check ^ ansbuf[j]; //计算校验码
TI0 = 0;
SBUF0 = ansbuf[j]; //发送数据
while(TI0 == 0) ;
}
ansbuf[6] = check; //发送校验码
TI0 = 0;
SBUF0 = ansbuf[6];
while(TI0 == 0);
}
///////////////////////////////////////////////////////////////////////////////////////////////
//最优化
//功能:进行最优化测量和上传最优化结果
///////////////////////////////////////////////////////////////////////////////////////////////
void BeginOptim(void) //8最优化函数
{
unsigned int data i,j;
unsigned int data temp;
unsigned int data optim_count;
unsigned long data total;
xples = rebuf[6] *256 + rebuf[7]; //读取上位机发送来的最优化数据
bright = rebuf[9];
time = rebuf[11];
count = rebuf[13];
optim_flag = 0;
optim_count = 0;
while((optim_flag==0)&&(optim_count<20)&&(time>0)&&(time<65)) //优化标志为0,积分次数小于20,积分时间0-65
{
optim_count ++;
Measure(XOPTaddr); //调用测量函数,XOPTaddr为最优化计算值的存放区
total = 0;
for(i=0; i<128; i++)
{
j = i + i;
temp = XBYTE[XOPTaddr+j] * 256 + XBYTE[XOPTaddr+j+1];
total = total + temp;
}
total = total /128;
if(total<MIDL)
{
if((total<MIDLL)&&(bright<=7)) bright++;
else time++;
}
else if(total>MIDH)
{
if((total>MIDHH)&&(bright>0))
{
if(bright == 8) time--;
else if(bright > 8) bright--;
else if(time > 25) time = 25;
else time--;
}
else time--;
}
else optim_flag = 1;
}
XPLESH = rebuf[6];
XPLESL = rebuf[7];
XBRIGHT = bright;
XTIME = time;
XCOUNT = count;
XVOLTH = (int)total/256;
XVOLTL = (int)total%256;
FlashWrite();
}
void OptimResult(void) //9发送最优化结果函数
{
unsigned int data i;
unsigned char data check = 0;
ansbuf[0] = 0x01;
ansbuf[1] = 0x03;
ansbuf[2] = 0x00;
ansbuf[3] = 0x08;
if(optim_flag==1)
{
ansbuf[4] = XPLESH;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -