1、引言
数据采集系统是组成现代测量仪器的基础,设计中单片机89C51、A/D转换器、存储器、D/A转换器及一些译码器、寄存器、多路开关芯片等组成一个完整的数据采集系统。这种设计方法使用的器件较多,系统复杂,成本高,系统开发时间比较长。而采用集成了A/D转换、定时/计数器等电路的数据采集芯片的系统设计能大大降低系统开发时间和成本、缩小设备体积、提高系统的可靠性和电气性能指标。因此,具有高速、高性能、高集成度并与8051完全兼容的单片机就显得非常需要。美国Cygnal公司新近推出的C8051Fxxx系列单片机正好满足这些需求。下面就该产品中适用于高精度数据采集系统的C8051F060 单片机进行探讨。 2、C8051F060 单片机简介 C8051F060单片机是美国Silabs公司推出的一种与51系列单片机内核兼容的单片机。仅就笔者对C8051F060的使用实践介绍一下其新特点: ⑴CPU C8051F060 单片机采用Cygnal公司的专利CIP51微处理器内核。CIP51在提升8051速度上采取了新的途径,即设法在保持CISC 结构及指令系统不变的情况下,对指令运行实行流水作业。速度25MIPS(25MHZ晶振),比普通的51单片机快10倍;其指令与标准系列51单片机兼容,因而掌握开发过程非常容易;该芯片的JTAG调试方式支持在系统、全速、非插入调试和编程,且不占用片内资源。 ⑵存储器及ADC、DAC
片上集成有64KB Flash、4352B内部RAM(256+4KB,可外扩至64KB)、59个I/O口、2通道16位1MSPS的可编程增益ADC、8通道10位200KSPS可编程增益ADC、2路12位DAC、3路模拟比较器、内部电压基准以及片内电源监视、降压检测和看门狗等功能。由于C8051F060的高集成度,因而无需外扩ROM、RAM、AD、DA、watchdog、编程I/O口和EEPROM(用片内Flash实现),从而大大简化了硬件电路,并为构成以C8051F060为核心的单片机系统创造了条件,同时也提高了系统的可靠性。 ⑶串行总线 C8051F060单片机除设计有标准的全双工UART之外, 还设有I2C?SMBus,SPI串行总线等多类型串行总线端口, 且通讯功能更加强大。最为便利的是, C8051F060集成了CAN总线控制器,这使得CAN总线具有开发费用低廉、抗干扰性强、可适用于工业现场应用等特点,并可广泛应用于干扰环境非常严重的各种工业现场测控领域。C8051F060只需加上CAN总线收发电路就可挂接到CAN通信网络上,因而大大简化了通信系统的设计,减少了通信节点受干扰的概率。 ⑷适应性 C8051F060能满足绝大多数工业测控节点的要求,能够形成以C8051F060为核心的单片机系统,如果配以外围测量单元,还可形成完整的测控节点。 3、C8051F060在数据采集系统中的应用
由于C8051F060芯片具有大量的优点,它的应用领域也十分广泛,下面介绍一个它在数据采集系统中的例子。本例子主要是将井下加速度传感器敏感的三轴加速度GX、GY、GZ以及电池电压Vbat井底温度传感器输出Vtemp五个电量进行采集并存储。 3.1硬件部分
硬件部分主要由多路开关、单片机、偏置电路(由于该单片机只能采集正信号,故加一偏置电路将-5V~+5V转换到0V~+5V)组成。其电路原理图如图一:
3.2软件部分
在实际应用时,当上电后该系统处于等待状态,当接到PC机的启动命令后,开始按测量任务进行数据采集、处理、存储。其主程序框图如下:
其中: (1) 初始化部分:主要是对C8051F060单片机的配置,它包括:
端口初始化:主要完成对端口p0~p7的初始化配置;
串口初始化:主要完成对定时计数器T0,T1配置及对波特率的设定;
定时器3初始化:主要完成对定时器3的重装载值的设定;
系统时钟初始化:主要完成对内外部振荡器使用的配置; ADC0初始化:主要完成对ADC0的配置,包括参考电压的选择、激发采集方式的设置等; (2) 读启动标志:当井下CPU接收到地面发送的启动标志"AA55"时,才开始采集,否则一直等待;
(3) 读参数:读取应采样点数和时间间隔使得采集按我们的要求进行; (4) 采集:通过选用定时器3的溢出激发采集方式,来采集我们所需的电压值; (5) 存储:将采集的数据一定的格式存入到存储器中。
单片机程序采用C51完成,部分源程序如下: (1) 端口初始化 void PORT_Init (void) { char old_SFRPAGE = SFRPAGE; SFRPAGE = CONFIG_PAGE; //切换到配置页 XBR0 = 0x05; //允许UART0 XBR1 = 0x00; XBR2 = 0x44; //允许交叉开关,端口I/O弱上拉允许 P0MDOUT|= 0xFF; //允许P0口为推挽输出 SFRPAGE = old_SFRPAGE; //返回起始特殊功能寄存器页 } (2) 串口初始化 void UART0_Init (void) { char old_SFRPAGE = SFRPAGE; SFRPAGE = UART0_PAGE; //切换到UART0页 SCON0 = 0x50; // SCON:方式1,8-bit UART,允许接收 SSTA0 = 0x10; //定时器1位波特率发生器 SFRPAGE = TIMER01_PAGE; //切换到Timer 0/1页 TMOD = 0x20; // TMOD:定时器1,方式2,8为重装载 TH1 = -(SYSCLK/BAUDRATE/16); //根据波特率设置定时器1重载值 TR1 = 1; //启动定时器1 CKCON | = 0x10; //定时器1使用SYSCLK作为时基 PCON | = 0x80; // SMOD = 1 SFRPAGE = UART0_PAGE; //切换到UART0页 TI0 = 1; //表示TX0准备好 SFRPAGE = old_SFRPAGE; //返回起始特殊功能寄存器页 } (3) 定时器3初始化 void Timer3_Init (int counts) { char old_SFRPAGE = SFRPAGE; SFRPAGE = TMR3_PAGE; //切换到定时器3页 TMR3CN = 0x00; //停止定时器3;清除TF3 TMR3CF = 0x08; //使用SYSCLK作为时基 RCAP3 = -counts; //初始化重载值 TMR3 = counts; //立即开始重装载 EIE2 |= 0x01; //允许定时器3中断 TR3 = 1; //启动定时器3 SFRPAGE = old_SFRPAGE; //返回起始特殊功能寄存器页 } (4) 系统时钟初始化 void SYSCLK_Init (void) { char old_SFRPAGE = SFRPAGE; int i; SFRPAGE = CONFIG_PAGE; //切换到配置页 OSCXCN = 0x67; //启动外部振荡器 for (i=0; i <5000; i++) ; //等待振荡器启振 while (!(OSCXCN & 0x80)) ; //等待晶体振荡器稳定 RSTSRC = 0x04; //允许时钟丢失检测器 CLKSEL = 0x01; //选择外部始终 OSCICN = 0x00; //禁止内部时钟 SFRPAGE = old_SFRPAGE; //返回起始特殊功能寄存器页 } (5) ADC0初始化 void ADC0_Init (void) { char old_SFRPAGE = SFRPAGE; int i; SFRPAGE = ADC0_PAGE; //切换到ADC0页 ADC0CN = 0x04; // 禁止ADC0,定时器3溢出启动ADC0转换 REF0CN = 0x03; //选择内部参考电压 for(i=0;i<10000;i++); // AMX0SL = 0x00; //单端方式 ADC0CF = (SYSCLK/25000000) << 4; //选择SAR时钟频率约为25MHz EIE1 |=0x80; SFRPAGE = old_SFRPAGE; //返回起始特殊功能寄存器页 } (6) AD转换完成 void AD_Complete (void) interrupt 13 { char old_SFRPAGE = SFRPAGE; SFRPAGE = ADC0_PAGE ; //切换到ADC0页 AD_Con = ADC0; //存AD转换值 AD0INT = 0; //禁止ADC0中断 SFRPAGE = old_SFRPAGE; } |