初级会员
- 积分
- 126
- 金钱
- 126
- 注册时间
- 2016-5-9
- 在线时间
- 12 小时
|
[mw_shl_code=c,true]#include <c8051f020.h> // SFR declarations
#include <stdio.h>
#include <intrins.h>
#include "GPS.h"
//
// 特殊功能寄存器配置地址
//-----------------------------------------------------------------------------
sfr16 ADC0 = 0xbe; //16位SFR数据位地址为0xBE
sfr16 RCAP2 = 0xca; //当定时器2被配置为捕捉方式时寄存器地址,RCAP2L寄存器捕捉定时器2的低字节。
//当定时器2被配置为自动重装方式时,它保存重载值的低字节。
sfr16 RCAP3 = 0x92; //定时器3被配置为自动重装时寄存器地址,该寄存器保存重载值的低字节
sfr16 TMR2 = 0xcc; //定时器2低字节地址
sfr16 TMR3 = 0x94; //定时器3低字节地址
sbit LED = P1^6; //LED='1' 亮灯
sbit SW1 = P3^7; //SW1='0' 开关闭合
//-----------------------------------------------------------------------------
// 定义全局变量
//-----------------------------------------------------------------------------
#define BAUDRATE 115200 // 设置UART波特率
#define SYSCLK 22118400 // 外部晶振频率,开发板上的晶振
#define SAMPLE_RATE 50000 // 设置ADC0的采样率Hz。依据ADC0转换速率最高100ksps,因此最大采样率为100 000hz设置.
#define INT_DEC 256 // 过采样取平均值的次数。由过采样去平均值可提高ADC0的分辨率
#define SAR_CLK 2500000 // 理想的SAR时钟速度
#define SAMPLE_DELAY 50 // 采样延时50ms
#define ANALOG_INPUTS 2 // 两路输入管脚AIN0.0,AIN0.1
//-----------------------------------------------------------------------------
// 函数原型
//-----------------------------------------------------------------------------
void OSCILLATOR_Init (void);
void PORT_Init (void);
void UART0_Init (void);
void ADC0_Init (void);
void TIMER3_Init (void);
void ADC0_ISR (void);
void TIMER2_ISR (void);
void Uart_Receive(void);
void Wait_MS (unsigned int ms);
//-----------------------------------------------------------------------------
// 全局变量
//-----------------------------------------------------------------------------
long Result[ANALOG_INPUTS]; // ADC0 decimated value,模拟输入
unsigned char amux_input=0; // 多路模拟复用输入
unsigned char amux_convert=0;
unsigned char flag_data; //数据标志位
char xdata rev_buf[80]; //接收缓存
uchar xdata rev_start = 0; //接收开始标志
uchar xdata rev_stop = 0; //接收停止标志
uchar xdata gps_flag = 0; //GPS处理标志
uchar xdata num = 0; //
char xdata buf[80]; //接收缓存
//-----------------------------------------------------------------------------
// 子程序初始化
//-----------------------------------------------------------------------------
// 晶振初始化
//-----------------------------------------------------------------------------
//
// 返回值 : 无
// 参数 : 无
// 初始化使用22.1184MHz的晶振作为时钟源
//-----------------------------------------------------------------------------
void OSCILLATOR_Init (void)
{
int i; // 延时计数变量
OSCXCN = 0x67; // 启动外部晶振22.1184MHz
for (i=0; i < 256; i++) ; // 等待晶振启动
while (!(OSCXCN & 0x80)) ; // 检测晶振是否正常工作,若开始工作执行下面的程序
OSCICN = 0x88; // 选择外部晶振作为时钟源,使能打开时钟检测位
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// 端口初始化
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// 返回值 : 无
// 参数 : 无
//
// 本函数用于配置crossbar和GPIO端口.
// P0.0 数字推挽方式 UART TX
// P0.1 数字 漏极开关 UART RX
// P1.6 数字 推挽方式 LED
// AIN0.1 模拟输入 (无配置需要)
//-----------------------------------------------------------------------------
void PORT_Init (void)
{
XBR0 = 0x04; // Route UART0 to crossbar
XBR2 |= 0x40; // 使能交叉开关,弱上电
P0MDOUT |= 0x01; // 允许TX0作为推挽式输出
P1MDOUT |= 0x40; // 允许LED作为推挽式输出
P0MDOUT |= 0x01; // 设置TX1管脚为推挽式
P1MDOUT |= 0x40; // 设置LED(P1^6)为推挽式
}
//-----------------------------------------------------------------------------
// 串口初始化
//-----------------------------------------------------------------------------
//
// 返回值 : 无
// 参数 : 无
//
//使用定时器1配置UART0端口,串口其他设置为8——N——1
//
//-----------------------------------------------------------------------------
void UART0_Init (void)
{
SCON0 = 0x50; // SCON0: 模式 1, 8-bit UART, enable RX
TMOD = 0x20; // TMOD: timer 1, mode 2, 8-bit reload
TH1 = -(SYSCLK/BAUDRATE/16); // set Timer1 reload value for baudrate
TR1 = 1; // start Timer1
CKCON |= 0x10; // Timer1 uses SYSCLK as time base
PCON |= 0x80; // SMOD00 = 1
TI0 = 1; // 发送中断标志位
}
//-----------------------------------------------------------------------------
// ADC0_Init
//-----------------------------------------------------------------------------
//
// 返回值 : 无
// 参数 : 无
//
// 定时器3溢出标志着转换的完成,右对齐输出模式。使能ADC结束转换中断,关闭ADC
//
//-----------------------------------------------------------------------------
void ADC0_Init (void)
{
ADC0CN =0x04; // ADC0不工作;正常追踪保持模式; ADC0转换初始化右对齐
REF0CN = 0x07; // 温度传感器打开, 内部电压基准缓冲器工作。内部电压基准提供从 VREF 引脚输出
AMX0CF = 0x00; // AIN单端输入
AMX0SL = 0x00; // 选择AIN0.1管脚作为ADC mux的输入通道,ISR随着输入量发生改变
ADC0CF = (SYSCLK/SAR_CLK) << 3; // ADC转换时钟2.5MHz
ADC0CF |= 0x00; // PGA gain = 1 (default)
EIE2 |= 0x02; // ADC0转换结束中断
}
//-----------------------------------------------------------------------------
// TIMER3_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters :
// 1) none
//
// Configure Timer3 to auto-reload at interval specified by <counts> (no
// interrupt generated) using SYSCLK as its time base.
//
//-----------------------------------------------------------------------------
void TIMER3_Init (void)
{
TMR3CN = 0x02; // Stop Timer3; Clear TF3; set sysclk
// as timebase
RCAP3 = 65535 -(SYSCLK / 50000); // Init reload values for 20uS
TMR3 = RCAP3; // Set to reload immediately
EIE2 |= 0x01; // Disable Timer3 interrupts
TMR3CN |= 0x04; // start Timer3
}
//主函数
void main (void)
{
int hour,min,sec;
unsigned char i;
long measurement; // 电压单位是mV
//int Pressure; //压力单位是Mpa
WDTCN = 0xde; // 关闭看门狗定时器
WDTCN = 0xad;
OSCILLATOR_Init (); // 初始化晶振
PORT_Init (); // 初始化crossbar和GPIO
UART0_Init (); // 初始化UART0
TIMER3_Init (); // 初始化定时器3溢出时间为1ms
ADC0_Init (); // ADC初始化
AD0EN = 1; // 打开ADC
EA = 1; // 允许全局中断
while (1)
{
EA = 0; // 关闭中断
if((rev_stop==1)&&(buf[5]=='C'))//如果接收到GPS模块的GPRMC数据
{
ES=0;
hour= (buf [7]-0x30)* 16+ buf[8] -0x30;
min= (buf [9]-0x30)* 16+ buf[10]-0x30;
sec= (buf[11]-0x30)* 16+ buf[12]-0x30;
hour= hour / 16 * 10 + hour % 16;
hour= (hour+8) % 24;//UTC Time换算成北京时间
hour=hour/10*16+hour%10;
ES=1;
rev_stop=0;
}
for(i=0; i<2; i++)
{
// 12-bit的 ADC通过INT_DEC求平均得到电压值.
// 结果存储在Result中,右对齐
// 通过AIN 0.1口的电压计算方法式子:
// Vref (mV)
// measurement (mV) = --------------- * Result (bits)
// (2^12)-1 (bits)
measurement = Result * 2430 / 4095;
// Pressure=measurement*2.4/2.5/1000;
}
printf("shijian: %bu,AIN0.%bu voltage: %ld\tmv\n",hour,i,measurement);
EA = 1; // 重启中断
Wait_MS(SAMPLE_DELAY); // 等待下一次采样
}
}
//-----------------------------------------------------------------------------
// 中断服务程序
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// ADC0_ISR
//-----------------------------------------------------------------------------
//
// This ISR is called when the ADC0 completes a conversion. Each value is
// added to a running total <accumulator>, and the local decimation counter
// <int_dec> decremented. When <int_dec> reaches zero, we post the decimated
// result in the global variable <Result[]>.
//
// The analog input is sampled, held, and converted on a Timer2 overflow. To
// maximize input settling time, the analog mux is also advanced to the next
// input on the Timer2 overflow. Two different indices are held globally:
// amux_convert: index of the analog input undergoing conversion
// amux_input: index of the analog input selected in the analog
// multiplexer
//
//
//-----------------------------------------------------------------------------
void ADC0_ISR (void) interrupt 15
{
static unsigned int_dec=INT_DEC; // Integrate/decimate counter
// we post a new result when
// int_dec = 0
static long accumulator[ANALOG_INPUTS] ={0L};
// Here's where we integrate the
// ADC samples from input AIN0.0
unsigned char i;
AD0INT = 0; //clear ADC conversion complete overflow
accumulator[amux_convert] += ADC0; // Read ADC value and add to running
// total
if(amux_convert == (ANALOG_INPUTS-1))// reset input index if the last input
//was just read
{
int_dec--; // Update decimation counter
// when last of the analog inputs
// sampled
}
if (int_dec == 0) // If zero, then post result
{
int_dec = INT_DEC; // Reset counter
for(i=0; i<ANALOG_INPUTS; i++)
{
Result = accumulator >> 8; //Copy decimated values into Result
accumulator = 0L; // Reset accumulators
}
}
amux_convert = amux_input; // now that conversion results are
// stored, advance index to the analog
// input currently selected on the mux
LED = 1;
}
//-----------------------------------------------------------------------------
// TIMER2_ISR
//-----------------------------------------------------------------------------
//
// The timer2 overflow triggers the ADC0 conversion on the analog MUX input
// previously selected. It is permissable to change the analog MUX
// input once conversion has started, as the ADC has an internal sample
// and hold.
//
// This ISR routine will then select the next analog MUX input so as to
// maximize the settling time.
//
//-----------------------------------------------------------------------------
void TIMER2_ISR(void) interrupt 14
{
TMR3CN &= ~0x80; // 中断应答
amux_input ++; // 转向另一路模拟输入
if(amux_input == ANALOG_INPUTS) // 若读取到最后一位输入,则重新设置输入参数
{
amux_input=0; // 将输入重新设置为AIN0.0开始
}
AMX0SL = amux_input; // 为模拟复用选择下一个输入
LED = 0;
}
/***************************************************************/
/*************************单片机串口数据接收**************************/
/***************************************************************/
void Uart_Receive(void) interrupt 4
{
unsigned char ch,num;
ES = 0;
if (RI)//如果接收完成则进入
{
ch=SBUF;
if (ch == '$') //如果收到字符'$',便开始接收
{
rev_start = 1;
rev_stop = 0; //接收停止标志
}
if (rev_start == 1) //标志位为1,开始接收
{
buf[num++] = ch; //字符存到数组中
if (ch == '\n') //如果接收到换行
{
buf[num] = '\n';
rev_start = 0;
rev_stop = 1; //接收停止标志
num = 0;
}
}
}
RI = 0; //RI清0,重新接收
ES = 1; //串口1中断允许
}
//-----------------------------------------------------------------------------
// 延时子程序
//-----------------------------------------------------------------------------
//
// Return Value : 无
// Parameters:
// 1) unsigned int ms - number of milliseconds of delay
// range is full range of integer: 0 to 65335
//
// 本程序引入一个毫秒级的延时.
//
//-----------------------------------------------------------------------------
void Wait_MS(unsigned int ms)
{
CKCON &= ~0x20; // use SYSCLK/12 as timebase
RCAP2 = -(SYSCLK/1000/12); // Timer 2 overflows at 1 kHz
TMR2 = RCAP2;
ET2 = 0; // 禁止定时器2中断
TR2 = 1; // 打开定时器2
while(ms)
{
TF2 = 0; // 清除标志位初始化
while(!TF2); // 等待定时器溢出
ms--; // 时间减少
}
TR2 = 0; // 关闭定时器2
}[/mw_shl_code]
|
|