ARM学习之ADC实验
2011-10-19 14:06
246 查看
/***************************************************
Project: ADC实验
Writer: SHOW
Time:
2011/10/18
Hareware: 硬件平台:mini2440 , J-link.
Function: 通过调节mini2440的滑动变阻器W1 在SecureCRT终端看到电压从0V到3.299V的的连续变化。
Direction: 1.今天调了一上午都没出效果,调试发现一直停留在while(rADCCON & ADC_START);总是出不来。
开始以为是ADC_Convert转换函数不对,仔细检查没发现问题,再考虑可能是初始化函数不对,
所以AD转换不能真正开始,但是自己核对和别人可行的代码,查书,也没有发现有什么错误,
无奈之下,只能把别人可行的代码一段一段替代我的代码,再运行看效果,把JustDo的初始化函数
替代我的初始化函数Init_ADC,发现效果出来了,太Happy了,锁定问题就一定出在Init_ADC函数啦。
但是还有一个问题就是我的几乎和他的一模一样啊,怎么他的能出来,我的出不来了?再仔细分析
代码我的是rADCCON = (PRESCALE_EN | PRSCVL49 | CHANNEL0) ; 他的是rADCCON = (channel<<3) | (preScaler<<6) | (1<<14);
看了又看只有他的值直接赋给ADCCON寄存器,而我是或给它的。此刻!我完全清晰啦,肯定是ADCCON
上电初始value不是0。如果是或的话保留了其他值的其他位,这样肯定和你想要的设置不同啦。
查手册发现初始值真的不是0,而是0x3fc4。犯这个错误根本原因就是自己想当然了,没有仔细看手册,
并不是所有的寄存器初始value就是0。
参考书籍:韦东山《嵌入式linux应用完全开发手册》
***************************************************/
#include "2440addr.h"
#include "def.h"
#include "uart.h" //uart.c by xgc
#define PRESCALE_EN (1<<14)
#define PRSCVL49 (49<<6)
#define CHANNEL0 (0<<3)
#define ADC_START (1<<0)
#define ADC_END_FLAG (1<<15)
#define MPLL_200MHZ ((0x5c<<12) | (0x01<<4) | (0x02))
void Set_PCLK_50M(void);
U16 ADC_Convert(void);
void Init_ADC(void);
void Init_UART(void);
//========================================================================
// 函数名称: 延时1ms子函数
// 功能描述: 延时
// 参数: times为延时的ms数。
// 返回值: void
//========================================================================
void Delay1ms(int times)
{
int i;
for( ; times > 0; times-- )
for(i=400; i>0 ; i--);
}
//========================================================================
// 函数名称: 主函数
// 功能描述: 函数入口
// 参数: void
// 返回值: void
//========================================================================
void Main(void)
{
U16 voltage = 0; // voltage 为小数点后的值
float f_voltage; // f_voltage 是将转换都的值转算成实际电压的值
Set_PCLK_50M(); // 设置PCLK为50M
Init_UART();
Init_ADC();
Uart_Printf("\n ---UART程序BY SHOW---\n"); // UART_Printf 函数来源xgc的库uart.c
while(1)
{
f_voltage = ((float)ADC_Convert() * 3.3) / 1023.0;
voltage = (f_voltage - (int)f_voltage) * 1000;
Uart_Printf("\n Voltage is %d.%dV \n",(int)f_voltage,voltage);
rADCCON |= ADC_START;
//转换完毕后,再次启动,以完成连续检测电压,这句很重要,不要因为启动一次就够了。
}
}
//========================================================================
// 函数名称: ADC初始化函数
// 功能描述 初始化ADC,使能预分频功能,分频比设置为49+1=50,选择通道0,启动ADC转换。
// 参数: void
// 返回值: void
//========================================================================
void Init_ADC(void)
{
rADCCON = (PRESCALE_EN | PRSCVL49 | CHANNEL0) ; // 使能预分频功能。分频比设为(49+1),选择模拟通道0。
rADCCON |= ADC_START;
// 启动转换
rADCTSC &= ~(1<<2);
// 普通转换模式
}
//========================================================================
// 函数名称: ADC转换函数
// 功能描述 开始ADC转换,并且返回转换后的值。
// 参数: void
// 返回值: 转换后的值
//========================================================================
U16 ADC_Convert(void)
{
while(rADCCON & ADC_START);
// 当转换真正开始后[0]会自动清0
while(!(rADCCON & ADC_END_FLAG));
// 判断是否转换结束,[15]为1则转换结束
return(rADCDAT0 & 0x3ff);
// 转换结束后返回数字量,注意是ADCDAT0的后10位数据。
}
//========================================================================
// 函数名称: PCLK大小设置函数
// 功能描述 设置FCLK=200M,PCLk=50M
// 参数: void
// 返回值: void
//========================================================================
void Set_PCLK_50M(void)
{
rMPLLCON = 0;
rMPLLCON |= MPLL_200MHZ; // MPLL = FCLK
rCLKDIVN = 0x03; // FCLK:HCLK:PCLK = 1:2:4 => PCLK = 50MHz.
}
//========================================================================
// 函数名称: UART初始化子函数
// 功能描述: 设置UATR0的基本信息
// 参数: void
// 返回值: void
//========================================================================
void Init_UART(void)
{
rGPHCON |= ((1 << 7) | (1 << 5)); //设置 GPH2,GPH3 为TXD0,RXD0 口。
rGPHUP |= ((1 << 3) | (1 << 2));
rULCON0 = 0x03;
// 无红外模式,数据位为8位。
rUCON0 = 0x05;
// UART时钟源为PCLK。Transmit与Receive都为查询或者中断模式
rUFCON0 = 0x00;
// 不使用FIFO
rUMCON0 = 0x00;
// 不使用流控
rUBRDIV0 = (50000000 / (115200 * 16)) - 1; // 波特率为115200
}
Project: ADC实验
Writer: SHOW
Time:
2011/10/18
Hareware: 硬件平台:mini2440 , J-link.
Function: 通过调节mini2440的滑动变阻器W1 在SecureCRT终端看到电压从0V到3.299V的的连续变化。
Direction: 1.今天调了一上午都没出效果,调试发现一直停留在while(rADCCON & ADC_START);总是出不来。
开始以为是ADC_Convert转换函数不对,仔细检查没发现问题,再考虑可能是初始化函数不对,
所以AD转换不能真正开始,但是自己核对和别人可行的代码,查书,也没有发现有什么错误,
无奈之下,只能把别人可行的代码一段一段替代我的代码,再运行看效果,把JustDo的初始化函数
替代我的初始化函数Init_ADC,发现效果出来了,太Happy了,锁定问题就一定出在Init_ADC函数啦。
但是还有一个问题就是我的几乎和他的一模一样啊,怎么他的能出来,我的出不来了?再仔细分析
代码我的是rADCCON = (PRESCALE_EN | PRSCVL49 | CHANNEL0) ; 他的是rADCCON = (channel<<3) | (preScaler<<6) | (1<<14);
看了又看只有他的值直接赋给ADCCON寄存器,而我是或给它的。此刻!我完全清晰啦,肯定是ADCCON
上电初始value不是0。如果是或的话保留了其他值的其他位,这样肯定和你想要的设置不同啦。
查手册发现初始值真的不是0,而是0x3fc4。犯这个错误根本原因就是自己想当然了,没有仔细看手册,
并不是所有的寄存器初始value就是0。
参考书籍:韦东山《嵌入式linux应用完全开发手册》
***************************************************/
#include "2440addr.h"
#include "def.h"
#include "uart.h" //uart.c by xgc
#define PRESCALE_EN (1<<14)
#define PRSCVL49 (49<<6)
#define CHANNEL0 (0<<3)
#define ADC_START (1<<0)
#define ADC_END_FLAG (1<<15)
#define MPLL_200MHZ ((0x5c<<12) | (0x01<<4) | (0x02))
void Set_PCLK_50M(void);
U16 ADC_Convert(void);
void Init_ADC(void);
void Init_UART(void);
//========================================================================
// 函数名称: 延时1ms子函数
// 功能描述: 延时
// 参数: times为延时的ms数。
// 返回值: void
//========================================================================
void Delay1ms(int times)
{
int i;
for( ; times > 0; times-- )
for(i=400; i>0 ; i--);
}
//========================================================================
// 函数名称: 主函数
// 功能描述: 函数入口
// 参数: void
// 返回值: void
//========================================================================
void Main(void)
{
U16 voltage = 0; // voltage 为小数点后的值
float f_voltage; // f_voltage 是将转换都的值转算成实际电压的值
Set_PCLK_50M(); // 设置PCLK为50M
Init_UART();
Init_ADC();
Uart_Printf("\n ---UART程序BY SHOW---\n"); // UART_Printf 函数来源xgc的库uart.c
while(1)
{
f_voltage = ((float)ADC_Convert() * 3.3) / 1023.0;
voltage = (f_voltage - (int)f_voltage) * 1000;
Uart_Printf("\n Voltage is %d.%dV \n",(int)f_voltage,voltage);
rADCCON |= ADC_START;
//转换完毕后,再次启动,以完成连续检测电压,这句很重要,不要因为启动一次就够了。
}
}
//========================================================================
// 函数名称: ADC初始化函数
// 功能描述 初始化ADC,使能预分频功能,分频比设置为49+1=50,选择通道0,启动ADC转换。
// 参数: void
// 返回值: void
//========================================================================
void Init_ADC(void)
{
rADCCON = (PRESCALE_EN | PRSCVL49 | CHANNEL0) ; // 使能预分频功能。分频比设为(49+1),选择模拟通道0。
rADCCON |= ADC_START;
// 启动转换
rADCTSC &= ~(1<<2);
// 普通转换模式
}
//========================================================================
// 函数名称: ADC转换函数
// 功能描述 开始ADC转换,并且返回转换后的值。
// 参数: void
// 返回值: 转换后的值
//========================================================================
U16 ADC_Convert(void)
{
while(rADCCON & ADC_START);
// 当转换真正开始后[0]会自动清0
while(!(rADCCON & ADC_END_FLAG));
// 判断是否转换结束,[15]为1则转换结束
return(rADCDAT0 & 0x3ff);
// 转换结束后返回数字量,注意是ADCDAT0的后10位数据。
}
//========================================================================
// 函数名称: PCLK大小设置函数
// 功能描述 设置FCLK=200M,PCLk=50M
// 参数: void
// 返回值: void
//========================================================================
void Set_PCLK_50M(void)
{
rMPLLCON = 0;
rMPLLCON |= MPLL_200MHZ; // MPLL = FCLK
rCLKDIVN = 0x03; // FCLK:HCLK:PCLK = 1:2:4 => PCLK = 50MHz.
}
//========================================================================
// 函数名称: UART初始化子函数
// 功能描述: 设置UATR0的基本信息
// 参数: void
// 返回值: void
//========================================================================
void Init_UART(void)
{
rGPHCON |= ((1 << 7) | (1 << 5)); //设置 GPH2,GPH3 为TXD0,RXD0 口。
rGPHUP |= ((1 << 3) | (1 << 2));
rULCON0 = 0x03;
// 无红外模式,数据位为8位。
rUCON0 = 0x05;
// UART时钟源为PCLK。Transmit与Receive都为查询或者中断模式
rUFCON0 = 0x00;
// 不使用FIFO
rUMCON0 = 0x00;
// 不使用流控
rUBRDIV0 = (50000000 / (115200 * 16)) - 1; // 波特率为115200
}
相关文章推荐
- Linux独立中断栈学习笔记及验证实验(ARM、x86)
- 【ARM学习笔记】实验四:内存管理单元MMU的虚拟地址映射实验
- 【iCore1S 双核心板_ARM】例程八:ADC实验——电源监控
- ARM学习之UART实验
- 【iCore4 双核心板_ARM】例程九:ADC实验——电源监控
- ARM学习之触摸屏实验
- ARM学习之KEY_ENT实验
- ARM学习之LCD实验
- 【ARM学习笔记】实验一:S3C2440A的GPIO输出实验
- ARM学习之GPIO实验
- ARM串口实验,ADC实验,I2C实验
- 【ARM学习笔记】实验二:S3C2440A的GPIO输入实验
- 学习 ARM 系列 -- FS2410 开发板上的内存搬移实验
- ARM底层学习笔记-裸板实验程序解析-点亮LED
- 【ARM学习笔记】实验三:S3C2440A与内存SDRAM连接实验
- ARM底层学习笔记-裸板实验程序解析-点亮LED
- cortex_m3_stm32嵌入式学习笔记(十六):ADC实验(模数转换)
- Part3_lesson2---ARM指令分类学习
- 【iCore1S 双核心板_ARM】例程四:USART通信实验——通过命令控制LED
- ARM的定时器的学习