初级会员
- 积分
- 126
- 金钱
- 126
- 注册时间
- 2016-5-9
- 在线时间
- 12 小时
|
1金钱
本帖最后由 cjf1018 于 2016-7-5 11:30 编辑
怎么添加一个流量测量的代码?[mw_shl_code=c,true]//程序测量电压在外部ADC输入并打印,结果通过UART终端串口读出。
#include <c8051f020.h> // 特殊寄存器的声明
#include <stdio.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' 开关闭合
long Result; //定义变量类型为long型
//-----------------------------------------------------------------------------
// 定义全局变量
//-----------------------------------------------------------------------------
#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
//-----------------------------------------------------------------------------
// 函数原型
//-----------------------------------------------------------------------------
void OSCILLATOR_Init (void);
void PORT_Init (void);
void UART0_Init (void);
void ADC0_Init (void);
void TIMER3_Init (int counts);
void ADC0_ISR (void);
void Wait_MS (unsigned int ms);
//-----------------------------------------------------------------------------
// 主函数
//-----------------------------------------------------------------------------
void main (void)
{
long measurement; // 测量电压的单位mv
WDTCN = 0xde; // 关闭看门狗
WDTCN = 0xad;
//初始化函数
OSCILLATOR_Init ();
PORT_Init ();
UART0_Init ();
TIMER3_Init (SYSCLK/SAMPLE_RATE);
ADC0_Init ();
AD0EN = 1; // 打开ADC
EA = 1; // 允许中断
while (1)
{
EA = 0; // 禁止中断
// 12-bit的 ADC通过INT_DEC求平均得到电压值.
// 结果存储在Result中,右对齐
// 通过AIN 0.1口的电压计算方法式子:
// Vref (mV)
// measurement (mV) = --------------- * Result (bits)
// (2^12)-1 (bits)
measurement = Result * 2430 / 4095; //电压计算结果
EA = 1; // 重启中断
printf("AIN0.1 voltage: %ld mV\n",measurement);//Keil内部函数printf打印输出电压值
LED = ~SW1; // LED等的亮灭也反映了开关的情况
Wait_MS(SAMPLE_DELAY); // 等待50ms下一次采样
}
}
//-----------------------------------------------------------------------------
// 子程序初始化
//-----------------------------------------------------------------------------
// 晶振初始化
//-----------------------------------------------------------------------------
// 返回值 : None
// 参数 : None
// 初始化使用22.1184MHz晶振作为时钟源
void OSCILLATOR_Init (void)
{
int i; // 定义延时计数变量 i
OSCXCN = 0x67; // 启动外部晶振22.1184MHz
for (i=0; i < 256; i++) ; // 等待晶振启动
while (!(OSCXCN & 0x80)) ; // 检测晶振是否在运行,若正常工作则开始执行下面的程序
OSCICN = 0x88; // 将外部晶振作为系统时钟,使能打开时钟丢失检测位。
}
//-----------------------------------------------------------------------------
// 端口初始化
//-----------------------------------------------------------------------------
// 返回值 : None
// 参数 : None
//
// 本函数用于配置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; // 设置P1.6(LED)为推挽式
}
//-----------------------------------------------------------------------------
// UART0_Init
//-----------------------------------------------------------------------------
// 返回值 : None
// 参数 : None
//
// 使用定时器1配置UART1.for <baudrate> and 8-N-1.
//-----------------------------------------------------------------------------
void UART0_Init (void)
{
SCON0 = 0x50; // SCON0: mode 1, 8-bit UART, enable RX
TMOD = 0x20; // TMOD: timer 1, mode 2, 8-bit reload
TH1 = -(SYSCLK/BAUDRATE/16); // 计数寄存器赋初值
TR1 = 1; // 启动定时器1
CKCON |= 0x10; // Timer1 uses SYSCLK as time base
PCON |= 0x80; // SMOD00 = 1,波特率发生器,波特率加倍
TI0 = 1; // Indicate TX0 ready
}
void UART1_Init (void)
{
SCON1 = 0x50; // SCON0: mode 1, 8-bit UART, enable RX
TMOD = 0x20; // TMOD: timer 1, mode 2, 8-bit reload
TH1 = -(SYSCLK/BAUDRATE/16); // 计数寄存器赋初值
TR1 = 1; // 启动定时器1
CKCON |= 0x10; // Timer1 uses SYSCLK as time base
PCON |= 0x80; // SMOD00 = 1,波特率发生器,波特率加倍
TI1 = 1; // Indicate TX0 ready
}
//-----------------------------------------------------------------------------
// ADC0_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// Configure ADC0 to use Timer3 overflows as conversion source, to
// generate an interrupt on conversion complete, and to use right-justified
// output mode. Enables ADC end of conversion interrupt. Leaves ADC disabled.
//
//-----------------------------------------------------------------------------
void ADC0_Init (void)
{
ADC0CN = 0x04; // ADC0禁止,正常追踪模式,定时器3溢出时启动ADC0,ADC0寄存器数据右对齐
// REF0CN = 0x07; // Enable temp sensor, on-chip VREF,
// and VREF output buffer
AMX0CF = 0x00; // AIN输入为单端输入 (默认情况下)
AMX0SL = 0x01; // 选择AIN0.1引脚作为ADC mux输入
ADC0CF = (SYSCLK/SAR_CLK) << 3; // ADC转换时钟= 2.5MHz
ADC0CF |= 0x00; // ADC0内部放大器增益PGA gain = 1 (默认)
EIE2 |= 0x02; // 打开ADC中断,允许ADC0转换结束产生中断请求
}
//-----------------------------------------------------------------------------
// TIMER3_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters :
// 1) int counts - calculated Timer overflow rate
// range is postive range of integer: 0 to 32767
//
// Configure Timer3 to auto-reload at interval specified by <counts> (no
// interrupt generated) using SYSCLK as its time base.
//
//-----------------------------------------------------------------------------
void TIMER3_Init (int counts)
{
TMR3CN = 0x02; // 停止定时器3;清零TF3溢出标志位;将系统时钟作为时间基准
RCAP3 = -counts; // 初始化重载值
TMR3 = RCAP3; // 设置立即自动重载
EIE2 &= ~0x01; // 禁止中断
TMR3CN |= 0x04; //启动定时器
}
//-----------------------------------------------------------------------------
// 中断服务程序
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// ADC0_ISR
//-----------------------------------------------------------------------------
// Here we take the ADC0 sample, add it to a running total <accumulator>, and
// decrement our local decimation counter <int_dec>. When <int_dec> reaches
// zero, we post the decimated result in the global variable <Result>.
//
//-----------------------------------------------------------------------------
void ADC0_ISR (void) interrupt 15 //x*8+3=中断向量地址0x7B
{
static unsigned int_dec=INT_DEC; // Integrate/decimate counter
// we post a new result when
// int_dec = 0
static long accumulator=0L; // Here's where we integrate the
// ADC samples
AD0INT = 0; // Clear ADC conversion complete
// indicator
accumulator += ADC0; // 读取ADC数值并累加结果
int_dec--; // 更新int_dec数值,减1
if (int_dec == 0) // 若int_dec为0,则输出结果
{
int_dec = INT_DEC; // 重新设置计数器
Result = accumulator >> 8;
accumulator = 0L; // 重新设置累加器
}
}
//-----------------------------------------------------------------------------
// Support Subroutines
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Wait_MS
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters:
// 1) unsigned int ms - number of milliseconds of delay
// range is full range of integer: 0 to 65335
//
// This routine inserts a delay of <ms> milliseconds.
//
//-----------------------------------------------------------------------------
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; // Stop Timer 2
}
//-----------------------------------------------------------------------------
// End Of File
//-----------------------------------------------------------------------------[/mw_shl_code] |
最佳答案
查看完整内容[请看2#楼]
要求不高的话,先读电流通道,再读电压通道就可以了。开2个通道。
要求高,就要2个ADC,同时采集(保证电流电压同时擦剂)。然后依次读取。
|