新手求助,c8051f340的多通道adc输出问题
时间:10-02
整理:3721RD
点击:
全程序已贴出,在void ADC0ISR (void) interrupt 10(倒数第二个片段)里输出的result数组两个值是一样的,不知应该怎么改?求教。Thanks?(?ω?)?
#include "main.h"
#include "lcd.h"
#define BAUDRATE 115200
#define SYSCLK 22118400UL //采用外部晶振时,系统的时钟频率为22118400hz
#define INPUTS 2
bit uartPrintFlag=0;
uint32 voltageData=0;
uint32 currentData=0;
uchar vol[5];
uchar cur[5];
uchar idata PIN_MUX_TABLE[INPUTS] = {4,5};
uint8 input=0;
uint32 result[INPUTS];
void InitUart0(void)
{
if (SYSCLK/BAUDRATE/2/256 < 1) {
TH1 = -(SYSCLK/BAUDRATE/2);
CKCON &= ~0x0B; // T1M = 1; SCA1:0 = xx
CKCON |= 0x08;
} else if (SYSCLK/BAUDRATE/2/256 < 4) {
TH1 = -(SYSCLK/BAUDRATE/2/4);
CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 01
CKCON |= 0x01;
} else if (SYSCLK/BAUDRATE/2/256 < 12) {
TH1 = -(SYSCLK/BAUDRATE/2/12);
CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 00
} else {
TH1 = -(SYSCLK/BAUDRATE/2/48);
CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 10
CKCON |= 0x02;
}
/*初始化定时器1*/
TMOD|=0x20; //定时器1工作在8位自动重装方式
TL1=0;
TR1=1;
/*初始化串口*/
S0MODE=0; //8位的UART工作方式
REN0=1; //接收允许
PS0=1; //为了在中断里输出串口打印,串口的优先级设为最高
ES0=1; //打开串口中断
/*配置引脚*/
P0MDOUT |= 0x10; //串口TXD引脚配置为推挽输出方式,用于UART发送端
XBR0|=0x01; //在外设连接寄存器0上把UART0连接到引脚P0.4和P0.5
}
/********************************************************************
函数功能:将外部晶振配置为系统时钟。
入口参数:无。
返 回:无。
备 注:无。
********************************************************************/
void InitOSC(void)
{
P0MDIN &= ~0xC0; //P0.6, P0.7配置为模拟输入,用作外部晶振
P0SKIP |= 0xC0; //交叉开关跳过P0.6, P0.7脚,用作外部晶振
OSCXCN = (0x60 | 7); //配置为外部晶体不分频,配置晶体频率为10M~30M
delay(1024); //等待外部晶振开始工作,不可省略一定要做的步骤
while (!(OSCXCN & 0x80)); //一直读取标志位,直到外部晶体稳定
RSTSRC = 0x06; // Enable missing clock detector and VDD Monitor reset
CLKSEL = 0x01; //选择外部晶体为时钟
OSCICN = 0x00; //关闭内部晶振
}
/********************************************************************
函数功能:初始化定时器3,每5ms产生一个中断。
入口参数:无。
返 回:无。
备 注:无。
********************************************************************/
void InitTimer3(void)
{
/*22.1184M/12分频/200=9216,即5ms*/
TMR3RLL=(65536-9216)%256; //计数到0xFFFF再计一次发生溢出。(0xFFFF=65535)
TMR3RLH=(65536-9216)/256;
TMR3L=(65536-9216)%256;
TMR3H=(65536-9216)/256;
EIE1|=0x80; //允许T3中断
TMR3CN|=0x04; //启动定时器3,默认为16位自动重装方式,sysclk/12分频
}
/********************************************************************
函数功能:初始化初始化ADC0。
入口参数:无。
返 回:无。
备 注:无。
********************************************************************/
void InitADC0(void)
{
P2MDIN&=~0x60; //P2.5、P2.6配置为模拟输入,用作AD转换输入
P2SKIP|=0x60; //跳过P2.5、P2.6脚,用作AD转换输入
ADC0CN = 0x05; // 关闭ADC0, 设置正常跟踪方式, 由定时器3触发
REF0CN = 0x08; // 选择使用VCC作为电压基准
AMX0P = PIN_MUX_TABLE[0]; // ADC0正极输入选择
AMX0N = 0x1F; // ADC0负极输入选择为GND,即工作在单端模式
ADC0CF=((SYSCLK/3000000)-1)<<3; // SAR clock是供给ADC转换器的时钟,根据数据手册,SAR clock最快为3MHz
ADC0CF |= 0x00; // 转换结果右对齐
EIE1 |= 0x08; // 使能ADC0转换完成中断
AD0EN = 1; // 开启ADC0
}
char *itoa(int num, char *str, int radix) //itoa
{
char string[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char* ptr = str;
int i;
int j;
while (num)
{
*ptr++ = string[num % radix];
num /= radix;
if (num < radix)
{
*ptr++ = string[num];
*ptr = '\0';
break;
}
}
j = ptr - str - 1;
for (i = 0; i < (ptr - str) / 2; i++)
{
int temp = str;
str = str[j];
str[j--] = temp;
}
return str;
}
/********************************************************************
函数功能:主函数。
入口参数:无。
返 回:无。
备 注:无。
********************************************************************/
void main (void)
{
PCA0MD &= ~0x40; //WDTE = 0 关闭看门狗,上电默认打开
XBR1= 0x60; //打开交叉开关,使能弱上拉,要使GPIO生效,必须打开交叉开关
P2MDOUT=0x0D; //P2.2,P2.3配置为推挽方式,LED2,LED3
P1MDOUT=0xE0; //1.5,1.6,1.7,配置为推挽方式,NUM_SER,NUM_SCK,NUM_RCK
P3MDOUT=0x1F;
InitOSC(); //初始化晶振
InitTimer3(); //初始化定时器3
InitADC0(); //初始化ADC0
InitUart0(); //初始化串口
EA=1; //允许所有中断
LED2=0;
LED3=0;
NUM_SCK=0; //上升沿数据移位,下降沿不变
NUM_RCK=0; //上升沿移位寄存器数据进入数据存储器,下降沿不变
while(1){
initial_lcd();
clear_screen();
if(uartPrintFlag){
uartPrintFlag=0;
itoa(voltageData,vol,10);
itoa(currentData,cur,10);
display_graphic_16x16(1,1,dian1);
display_graphic_16x16(1,1+16,ya1);
display_graphic_8x16(1,1+16*2,maohao);
display_string_8x16(1,41,vol);
display_string_8x16(1,1+16*5,"mV.");
display_graphic_16x16(3,1,dian1);
display_graphic_16x16(3,1+16,liu1);
display_graphic_8x16(3,1+16*2,maohao);
display_string_8x16(3,41,cur);
display_string_8x16(3,1+16*5,"mA.");
// Prints("Voltage = ");
// PrintLongDecimal(voltageData);
// Prints(" mV.\r\n");
delay(1000);
}
}
}
/********************************************************************
函数功能:ADC0的中断服务程序。
入口参数:无。
返 回:无。
备 注:注意手动清除标志位。
********************************************************************/
void ADC0ISR (void) interrupt 10
{
static uint32 accumulator[INPUTS]=0; //AD转换结果累加和
// static unsigned int measurement=0; //AD转换次数计数
uint8 i=0;
for(i=0;i<INPUTS;i++)
{
AD0INT=0;
AMX0P=PIN_MUX_TABLE;
delay(50);
accumulator +=ADC0;
result=accumulator;
accumulator=0;
}
voltageData = result[0] * 3300/1023; //计算出以mV为单位的转换结果,写入numData
currentData = (result[1] * 3300/1023-2410)*5;//计算出以mA为单位的转换结果,写入numData
uartPrintFlag=1; //设置更新数码管显示标志位
}
/********************************************************************
函数功能:定时器3的中断服务程序。
入口参数:无。
返 回:无。
备 注:注意手动清除标志位。
********************************************************************/
void Timer3_ISR (void) interrupt 14
{
static unsigned int count=0;
TMR3CN&=(~0x80); //手动清除标志位
count++;
if(count==100){ //5ms一次中断,接收到100次*2中断即为1秒
count=0;
LED2=!LED2;} //每1秒闪烁一次LED
}
#include "main.h"
#include "lcd.h"
#define BAUDRATE 115200
#define SYSCLK 22118400UL //采用外部晶振时,系统的时钟频率为22118400hz
#define INPUTS 2
bit uartPrintFlag=0;
uint32 voltageData=0;
uint32 currentData=0;
uchar vol[5];
uchar cur[5];
uchar idata PIN_MUX_TABLE[INPUTS] = {4,5};
uint8 input=0;
uint32 result[INPUTS];
void InitUart0(void)
{
if (SYSCLK/BAUDRATE/2/256 < 1) {
TH1 = -(SYSCLK/BAUDRATE/2);
CKCON &= ~0x0B; // T1M = 1; SCA1:0 = xx
CKCON |= 0x08;
} else if (SYSCLK/BAUDRATE/2/256 < 4) {
TH1 = -(SYSCLK/BAUDRATE/2/4);
CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 01
CKCON |= 0x01;
} else if (SYSCLK/BAUDRATE/2/256 < 12) {
TH1 = -(SYSCLK/BAUDRATE/2/12);
CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 00
} else {
TH1 = -(SYSCLK/BAUDRATE/2/48);
CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 10
CKCON |= 0x02;
}
/*初始化定时器1*/
TMOD|=0x20; //定时器1工作在8位自动重装方式
TL1=0;
TR1=1;
/*初始化串口*/
S0MODE=0; //8位的UART工作方式
REN0=1; //接收允许
PS0=1; //为了在中断里输出串口打印,串口的优先级设为最高
ES0=1; //打开串口中断
/*配置引脚*/
P0MDOUT |= 0x10; //串口TXD引脚配置为推挽输出方式,用于UART发送端
XBR0|=0x01; //在外设连接寄存器0上把UART0连接到引脚P0.4和P0.5
}
/********************************************************************
函数功能:将外部晶振配置为系统时钟。
入口参数:无。
返 回:无。
备 注:无。
********************************************************************/
void InitOSC(void)
{
P0MDIN &= ~0xC0; //P0.6, P0.7配置为模拟输入,用作外部晶振
P0SKIP |= 0xC0; //交叉开关跳过P0.6, P0.7脚,用作外部晶振
OSCXCN = (0x60 | 7); //配置为外部晶体不分频,配置晶体频率为10M~30M
delay(1024); //等待外部晶振开始工作,不可省略一定要做的步骤
while (!(OSCXCN & 0x80)); //一直读取标志位,直到外部晶体稳定
RSTSRC = 0x06; // Enable missing clock detector and VDD Monitor reset
CLKSEL = 0x01; //选择外部晶体为时钟
OSCICN = 0x00; //关闭内部晶振
}
/********************************************************************
函数功能:初始化定时器3,每5ms产生一个中断。
入口参数:无。
返 回:无。
备 注:无。
********************************************************************/
void InitTimer3(void)
{
/*22.1184M/12分频/200=9216,即5ms*/
TMR3RLL=(65536-9216)%256; //计数到0xFFFF再计一次发生溢出。(0xFFFF=65535)
TMR3RLH=(65536-9216)/256;
TMR3L=(65536-9216)%256;
TMR3H=(65536-9216)/256;
EIE1|=0x80; //允许T3中断
TMR3CN|=0x04; //启动定时器3,默认为16位自动重装方式,sysclk/12分频
}
/********************************************************************
函数功能:初始化初始化ADC0。
入口参数:无。
返 回:无。
备 注:无。
********************************************************************/
void InitADC0(void)
{
P2MDIN&=~0x60; //P2.5、P2.6配置为模拟输入,用作AD转换输入
P2SKIP|=0x60; //跳过P2.5、P2.6脚,用作AD转换输入
ADC0CN = 0x05; // 关闭ADC0, 设置正常跟踪方式, 由定时器3触发
REF0CN = 0x08; // 选择使用VCC作为电压基准
AMX0P = PIN_MUX_TABLE[0]; // ADC0正极输入选择
AMX0N = 0x1F; // ADC0负极输入选择为GND,即工作在单端模式
ADC0CF=((SYSCLK/3000000)-1)<<3; // SAR clock是供给ADC转换器的时钟,根据数据手册,SAR clock最快为3MHz
ADC0CF |= 0x00; // 转换结果右对齐
EIE1 |= 0x08; // 使能ADC0转换完成中断
AD0EN = 1; // 开启ADC0
}
char *itoa(int num, char *str, int radix) //itoa
{
char string[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char* ptr = str;
int i;
int j;
while (num)
{
*ptr++ = string[num % radix];
num /= radix;
if (num < radix)
{
*ptr++ = string[num];
*ptr = '\0';
break;
}
}
j = ptr - str - 1;
for (i = 0; i < (ptr - str) / 2; i++)
{
int temp = str;
str = str[j];
str[j--] = temp;
}
return str;
}
/********************************************************************
函数功能:主函数。
入口参数:无。
返 回:无。
备 注:无。
********************************************************************/
void main (void)
{
PCA0MD &= ~0x40; //WDTE = 0 关闭看门狗,上电默认打开
XBR1= 0x60; //打开交叉开关,使能弱上拉,要使GPIO生效,必须打开交叉开关
P2MDOUT=0x0D; //P2.2,P2.3配置为推挽方式,LED2,LED3
P1MDOUT=0xE0; //1.5,1.6,1.7,配置为推挽方式,NUM_SER,NUM_SCK,NUM_RCK
P3MDOUT=0x1F;
InitOSC(); //初始化晶振
InitTimer3(); //初始化定时器3
InitADC0(); //初始化ADC0
InitUart0(); //初始化串口
EA=1; //允许所有中断
LED2=0;
LED3=0;
NUM_SCK=0; //上升沿数据移位,下降沿不变
NUM_RCK=0; //上升沿移位寄存器数据进入数据存储器,下降沿不变
while(1){
initial_lcd();
clear_screen();
if(uartPrintFlag){
uartPrintFlag=0;
itoa(voltageData,vol,10);
itoa(currentData,cur,10);
display_graphic_16x16(1,1,dian1);
display_graphic_16x16(1,1+16,ya1);
display_graphic_8x16(1,1+16*2,maohao);
display_string_8x16(1,41,vol);
display_string_8x16(1,1+16*5,"mV.");
display_graphic_16x16(3,1,dian1);
display_graphic_16x16(3,1+16,liu1);
display_graphic_8x16(3,1+16*2,maohao);
display_string_8x16(3,41,cur);
display_string_8x16(3,1+16*5,"mA.");
// Prints("Voltage = ");
// PrintLongDecimal(voltageData);
// Prints(" mV.\r\n");
delay(1000);
}
}
}
/********************************************************************
函数功能:ADC0的中断服务程序。
入口参数:无。
返 回:无。
备 注:注意手动清除标志位。
********************************************************************/
void ADC0ISR (void) interrupt 10
{
static uint32 accumulator[INPUTS]=0; //AD转换结果累加和
// static unsigned int measurement=0; //AD转换次数计数
uint8 i=0;
for(i=0;i<INPUTS;i++)
{
AD0INT=0;
AMX0P=PIN_MUX_TABLE;
delay(50);
accumulator +=ADC0;
result=accumulator;
accumulator=0;
}
voltageData = result[0] * 3300/1023; //计算出以mV为单位的转换结果,写入numData
currentData = (result[1] * 3300/1023-2410)*5;//计算出以mA为单位的转换结果,写入numData
uartPrintFlag=1; //设置更新数码管显示标志位
}
/********************************************************************
函数功能:定时器3的中断服务程序。
入口参数:无。
返 回:无。
备 注:注意手动清除标志位。
********************************************************************/
void Timer3_ISR (void) interrupt 14
{
static unsigned int count=0;
TMR3CN&=(~0x80); //手动清除标志位
count++;
if(count==100){ //5ms一次中断,接收到100次*2中断即为1秒
count=0;
LED2=!LED2;} //每1秒闪烁一次LED
}