基于友善之臂ARM-ContexA9-ADC驱动开发

简介: 基于友善之臂ARM-ContexA9-ADC驱动开发

版权声明:本文为博主原创文章,如有需要,请注明转载地址:http://blog.csdn.net/morixinguan。若是侵权用于商业用途,请联系博主,否则将追究责任

ADC,就是模数转换器,什么是模数转换器?

模数转换器,在电子技术中即是将模拟信号转换成数字信号,也称为数字量化。

当然还有一种叫DAC,就是数模转换,意思相反,即是将数字信号转换成模拟信号。

在友善之臂ARM-contexA9这款开发板上的4412芯片本身就自带了一个ADC的接口,我们来看看基本介绍:

0.jpg

数据手册开篇介绍了这么多,最有用的一句话:精度10位或12位CMOS模数转换器(ADC)包括多路模拟输入。灵敏度为1M,一共有4路输入,支持较低的电源模式等。

接下来我们还是跟以前一样:

1、先看电路原理图:


640.png

640.png

从原理图和核心板上可以看出可调电阻的IO对应数据手册的是AIN[0]。

640.jpg

2、看数字手册相关的寄存器

(1)ADC控制寄存器

640.jpg

寄存器的地址为:0x126C0000

在这里,我们要如何配置呢?

[0] 第0位:判断A/D转换有没有开始

[2] 第2位:配置模式位(正常的,标准的,我们这里选择默认为0)

[6:13]第6~13位:这里要配置预分频系数,我们配置为49,对应的公式就是:ADCCLK=PCLK/(49+10)=100MHZ / 50 =2MHZ

[14]第14位:选择使能预分频,写1到这个位去就可以了

[15]第15位:判断A/D转换结束了没有

[16]第16位:设置转换的精度(10或者12,自己选)

(2)ADC数据寄存器

640.png

基地址:0x126C000C

[11:0] 第0~11位:ADC转换的数据

(2)ADC通道选择寄存器

640.jpg

基地址:0x12C001C

ADCMUX[0:3]:这里我们配置为0000,也就是通道0

3、写代码

config.h

<span style="font-size:18px;">#ifndef __CONFIG_H__  
#define __CONFIG_H__
#define udelay  ((void (*)(unsigned int ))0x43e25e88)     //定义udelay在uboot中的地址,这样我们就可以使用这个函数
#define print   ((int (*)(const char *, ...))0x43e11434)  //定义printf在uboot中的地址
typedef unsigned int u32;  
typedefvolatile u32 v32;  
//设置位
#define set_one(reg, bit)   \
                ((*(v32 *)reg) |= (1<<bit))  
#define set_zero(reg, bit)  \
                ((*(v32 *)reg) &= (~(1<<bit)))  
#define set_bit(reg, bit, val)  \
                (*(v32 *)reg = (((*(v32 *)reg) & (~(1<<bit))) | (val << bit)))  
#define set_2bit(reg, bit, val) \
                (*(v32 *)reg = (((*(v32 *)reg) & (~(3<<bit))) | (val << bit)))  
#define set_nbit(reg, bit, n, val)  \
                (*(v32 *)reg = (((*(v32 *)reg) & (~( ((1<<n)-1) <<bit))) \  
                                    | (val << bit)))  
#define set_val(reg, val)   \
                ((*(v32 *)reg) = val)  
#define get_bit(reg, bit)   \
                (((*(v32 *)reg) & (1<<bit)) >> bit)  
#define get_2bit(reg, bit)  \
                (((*(v32 *)reg) & (3<<bit)) >> bit)  
#define get_nbit(reg, bit, n)   \
                (((*(v32 *)reg) & (((1<<n)-1) <<bit)) >> bit)  
#define get_val(reg)        \
                (*(v32 *)reg)  
#endif</span>
<span style="font-size:18px;">#ifndef __CONFIG_H__
#define __CONFIG_H__
#define udelay  ((void (*)(unsigned int ))0x43e25e88)     //定义udelay在uboot中的地址,这样我们就可以使用这个函数
#define print ((int (*)(const char *, ...))0x43e11434)  //定义printf在uboot中的地址
typedef unsigned int u32;
typedef volatile u32 v32;
//设置位
#define set_one(reg, bit) \
        ((*(v32 *)reg) |= (1<<bit))
#define set_zero(reg, bit)  \
        ((*(v32 *)reg) &= (~(1<<bit)))
#define set_bit(reg, bit, val)  \
        (*(v32 *)reg = (((*(v32 *)reg) & (~(1<<bit))) | (val << bit)))
#define set_2bit(reg, bit, val) \
        (*(v32 *)reg = (((*(v32 *)reg) & (~(3<<bit))) | (val << bit)))
#define set_nbit(reg, bit, n, val)  \
        (*(v32 *)reg = (((*(v32 *)reg) & (~( ((1<<n)-1) <<bit))) \
                  | (val << bit)))
#define set_val(reg, val) \
        ((*(v32 *)reg) = val)
#define get_bit(reg, bit) \
        (((*(v32 *)reg) & (1<<bit)) >> bit)
#define get_2bit(reg, bit)  \
        (((*(v32 *)reg) & (3<<bit)) >> bit)
#define get_nbit(reg, bit, n) \
        (((*(v32 *)reg) & (((1<<n)-1) <<bit)) >> bit)
#define get_val(reg)    \
        (*(v32 *)reg)
#endif</span>

adc.h

<span style="font-size:18px;">#ifndef __ADC_H__  
#define __ADC_H__
#define ADCCON 0x126C0000     //ADC控制寄存器
#define ADCDAT 0x126C000C     //ADC数据寄存器
#define ADCMUX 0x126C001C     //ADC通道寄存器
#define CLRINTADC   0x126C0018  //清除ADC中断
#endif</span>
<span style="font-size:18px;">#ifndef __ADC_H__
#define __ADC_H__
#define ADCCON 0x126C0000     //ADC控制寄存器
#define ADCDAT 0x126C000C     //ADC数据寄存器
#define ADCMUX 0x126C001C     //ADC通道寄存器
#define CLRINTADC 0x126C0018  //清除ADC中断
#endif</span>

adc.c

<span style="font-size:18px;">#include <adc.h>  
#include <config.h>
void select_mux(void)  
{  
    set_nbit(ADCMUX, 0, 4, 0x0);   //设置通道为通道0
}  
void adc_init(void)  
{  
    set_val(ADCCON, ((1<<16)|(1<<14)|(49<<6)));   //按照数据手册参数来配置adc控制寄存器的初始化部分
}  
void adc_start(void)  
{  
    set_one(ADCCON, 0);   //adc转换开始的配置,默认参数为0
}  
int adc_wait_flag(void)  
{  
    return get_bit(ADCCON, 15);<span style="white-space:pre"> </span>//AD转换是否成功
}  
int adc_data(void)  
{  
    return get_nbit(ADCDAT, 0, 12); //获取ADC数据
}     
void clear_adc(void)  
{  
    set_val(CLRINTADC, 0);<span style="white-space:pre">  </span>//清ADC
}</span>  
<span style="font-size:18px;">#include <adc.h>
#include <config.h>
void select_mux(void)
{
  set_nbit(ADCMUX, 0, 4, 0x0);   //设置通道为通道0
}
void adc_init(void)
{
  set_val(ADCCON, ((1<<16)|(1<<14)|(49<<6))); //按照数据手册参数来配置adc控制寄存器的初始化部分
}
void adc_start(void)
{
  set_one(ADCCON, 0);   //adc转换开始的配置,默认参数为0
}
int adc_wait_flag(void)
{
  return get_bit(ADCCON, 15);<span style="white-space:pre"> </span>//AD转换是否成功
}
int adc_data(void)
{
  return get_nbit(ADCDAT, 0, 12); //获取ADC数据
} 
void clear_adc(void)
{
  set_val(CLRINTADC, 0);<span style="white-space:pre">  </span>//清ADC
}</span>

main.c

<span style="font-size:18px;">#include <config.h>  
#include <adc.h>
int main(void)  
{     
    //设置ADC通道为通道0
    select_mux();  
    //adc初始化
    adc_init();  
    //adc转换开始
    adc_start();  
    while(1)  
    {  
        //判断是否已经转换
        if(adc_wait_flag())  
        {  
            //打印相应的数据
            print("data = %d\n",adc_data());  
            //重新adc转换开始
            adc_start();  
        }  
    }     
    return 0;  
}</span>  
<span style="font-size:18px;">#include <config.h>
#include <adc.h>
int main(void)
{ 
  //设置ADC通道为通道0
  select_mux();
  //adc初始化
  adc_init();
  //adc转换开始
  adc_start();
  while(1)
  {
    //判断是否已经转换
    if(adc_wait_flag())
    {
      //打印相应的数据
      print("data = %d\n",adc_data());
      //重新adc转换开始
      adc_start();
    }
  } 
  return 0;
}</span>

4、makefile略

5、观察结果

先让uboot启动

640.jpg

然后用dnw下载程序:

640.jpg

最后旋转电阻观察数据变化:

640.jpg

目录
相关文章
|
6月前
|
算法 编译器 Linux
【Qt4 部署】ARM系统上使用Qt 4 进行开发的QWS 等环境变量部署
【Qt4 部署】ARM系统上使用Qt 4 进行开发的QWS 等环境变量部署
122 0
|
3月前
|
编解码 安全 Linux
基于arm64架构国产操作系统|Linux下的RTMP|RTSP低延时直播播放器开发探究
这段内容讲述了国产操作系统背景下,大牛直播SDK针对国产操作系统与Linux平台发布的RTMP/RTSP直播播放SDK。此SDK支持arm64架构,基于X协议输出视频,采用PulseAudio和Alsa Lib处理音频,具备实时静音、快照、缓冲时间设定等功能,并支持H.265编码格式。此外,提供了示例代码展示如何实现多实例播放器的创建与管理,包括窗口布局调整、事件监听、视频分辨率变化和实时快照回调等关键功能。这一技术实现有助于提高直播服务的稳定性和响应速度,适应国产操作系统在各行业中的应用需求。
109 3
|
6月前
|
Linux 开发工具 芯片
玩转 PI 系列 - 如何在 Rockchip Arm 开发板上安装 Docker Tailscale K3s Cilium?
玩转 PI 系列 - 如何在 Rockchip Arm 开发板上安装 Docker Tailscale K3s Cilium?
|
6月前
|
存储 Ubuntu Linux
ARM-Linux开发与MCU开发的不同之处分析
ARM-Linux开发与MCU开发的不同之处分析
67 0
ARM6818开发板画任意矩形,圆形,三角形,五角星,6818开发板画太极,画五星红旗(含码源与思路)
ARM6818开发板画任意矩形,圆形,三角形,五角星,6818开发板画太极,画五星红旗(含码源与思路)
541 0
|
Linux C++
基于ARM-contexA9-Linux驱动开发:如何获取板子上独有的ID号
基于ARM-contexA9-Linux驱动开发:如何获取板子上独有的ID号
127 0
|
缓存 C++
基于ARM-contexA9-蜂鸣器pwm驱动开发
基于ARM-contexA9-蜂鸣器pwm驱动开发
109 0
基于ARM-contexA9蜂鸣器驱动开发
基于ARM-contexA9蜂鸣器驱动开发
103 0
|
算法 物联网 测试技术
开发一个arm固件加载基址定位器
最近入坑iot,涉及很多芯片固件的逆向。但是这些固件很多时候都不是标准二进制格式,也就是说丢进ida,识别不出架构和指令集。架构和指令集可以查芯片的文档,但是加载基址还没法确定,这个靠自己去定位,再配置ida。人工做这个工作太累,而我又是懒狗,所以自动化这一过程不香吗?
|
30天前
|
编解码 弹性计算 应用服务中间件
阿里云服务器Arm计算架构解析:Arm计算架构云服务器租用收费标准价格参考
阿里云服务器架构分为X86计算、Arm计算、高性能计算等多种架构,其中Arm计算架构以其低功耗、高效率的特点受到广泛关注。本文将深入解析阿里云Arm计算架构云服务器的技术特点、适用场景以及包年包月与按量付费的收费标准与最新活动价格情况,以供选择参考。

热门文章

最新文章