首页 > 其他分享 >基于I.MX6UL平台的ADS1256驱动开发四.IC操作

基于I.MX6UL平台的ADS1256驱动开发四.IC操作

时间:2022-12-18 22:34:42浏览次数:44  
标签:读取 uint8 发送 MX6UL 寄存器 gpio IC ADS1256

在前面章节我们已经完成了最基础的驱动框架的搭建,下面就需要在GPIO可以正常工作的条件下进行IC的读写操作。首先我们要完成最基础的读写操作,然后所有的操作都是基于这个读写操作都基础上完成的。

写入值

对IC进行的所有操作都基于写入数据的基础上衍生来的,比如想要读取AD转换后的码值也要写入对应的指令。不管是写入命令还是写入数据,方法都是一样的。可以对照前面第一章节里的串口时序图,看一下写入过程的时序要求

 

 

 注意下SPI的工作模式:时钟在空闲时候为低电平,即CPOL=0;数据位在时钟的第一个跳变沿进行采样,即CPHA=0。

然后t1的值需要满足大于4个CLKIN,也就是0.53us;小鱼10个采样周期。采样周期在30K的时候最小,大约是0.033ms,10个DATA周期就是0.3ms。为并且高低电平的最小时长要满足200ns。

我们先写一段宏,可以在后面的程序中判定或设置GPIO高低的状态。

#define CS_0()        gpio_set_value(ads1256_dev.cs_gpio, 0)
#define CS_1()        gpio_set_value(ads1256_dev.cs_gpio, 1)

#define SCK_0()       gpio_set_value(ads1256_dev.clk_gpio, 0)
#define SCK_1()       gpio_set_value(ads1256_dev.clk_gpio, 1)

#define DI_0()        gpio_set_value(ads1256_dev.mosi_gpio, 0)
#define DI_1()        gpio_set_value(ads1256_dev.mosi_gpio, 1)

#define DO_IS_HIGH()  gpio_get_value(ads1256_dev.miso_gpio)==1

#define DRDY_IS_LOW() gpio_get_value(ads1256_dev.drdy_gpio)==0

我们要写个延时函数,用来满足SCLK信号的延时

/**
 * @brief 时钟延时
 * 
 */
static void ADS1256_DelaySCLK(void)
{
    uint16_t i;
    for (i = 0; i < 100; i++);
}

在默认的主频下(800MHz),for循环100次时间大概是3.5us,并且高低电平都满足不小于200ns的要求。

 满足要求。然后是发送8个bit数据的流程

 1 // /**
 2 //  * @brief 发送8bit数据
 3 //  * 
 4 //  * @param _data 
 5 //  */
 6 static void ADS1256_Send8Bit(uint8_t _data)
 7 {
 8     uint8_t i;
 9     /* 连续发送多个字节时,需要延迟一下 */
10     ADS1256_DelaySCLK();
11 
12     for(i = 0; i < 8; i++)
13     {
14         if (_data & 0x80)  //10000000b
15         {
16             DI_1();
17         }
18         else
19         {
20             DI_0();
21         }
22         SCK_1();                //时钟拉高
23         ADS1256_DelaySCLK();
24         _data <<= 1;
25         SCK_0();            /* <----  ADS1256 是在SCK下降沿采样DIN数据, 数据必须维持 50nS */
26         ADS1256_DelaySCLK();
27     }
28     DI_0();
29 }

注意一下,这里我们并没有对CS信号进行操作,因为这个函数是用来发送8个bit的,但是一般情况我们需要发送两个字节中间就不再操作cs信号了。发送8个bit的过程是在一个for循环里完成的,把传递进来的data和0x80进行与运算,也就是data的最高位如果是1就执行DI_1()的指令,MOSI输出高电平,否则MOSI输出低电平。该bit发送完成后data左移1位,进行第2个bit的判定,直至8个bit发送完毕。for循环中每次if或else语句执行完成后把时钟拉高,进行延时后拉低,重新延时,即一次循环体。

写命令

ADS1256的命令集合基本上都是8个bit的格式,我们可以直接调用发送的函数就可以

/**
 * @brief 发送命令
 * 
 * @param _cmd 
 */
static void ADS1256_WriteCmd(uint8_t _cmd)
{
    CS_0();    /* SPI片选 = 0 */
    ADS1256_Send8Bit(_cmd);
    CS_1();    /* SPI片选 = 1 */
}

就是在原有的函数上加上CS信号的操作。完成函数后我们可以在初始化的结尾加上这个函数测试一下

 这里贴了个图主要是要表明这个发送命令的函数要在哪调用。我们直接发送一个0xAB,可以测一下信号

 由于系统资源的问题,这个时钟周期要稍微长一些,大概是8.5us。

下面那个白色的就是MOSI发送出去的值,解析出来就是0xAB(时钟信号上升沿)。说明发送过程没问题。

写寄存器

写寄存器的过程要参考时序图

 

说白了就是分别写入三个部分的数据,第一个是第一个命令字,包括写命令和寄存器地址,第二个部分是写入寄存器的数量,后面是写入数据。我们先按照这个思路完成单个寄存器写入的流程。 

 1 /**
 2  * @brief 写单个寄存器
 3  * 
 4  * @param _RegID 
 5  * @param _RegValue 
 6  */
 7 static void ADS1256_WriteReg(uint8_t _RegID, uint8_t _RegValue)
 8 {
 9     CS_0();    /* SPI片选 = 0 */
10     ADS1256_Send8Bit(CMD_WREG | _RegID);    /* 写寄存器的命令, 并发送寄存器地址 */
11     ADS1256_Send8Bit(0x00);        /* 寄存器个数 - 1, 此处写1个寄存器 */
12 
13     ADS1256_Send8Bit(_RegValue);    /* 发送寄存器值 */    
14     CS_1();    /* SPI片选 = 1 */
15 }

先把片选信号拉低,然后发送包含地址和写命令的第一部分(第10行),然后发送写入寄存器-1,我们只写1个寄存器所以发送0x00,最后发送数据。

读取值

下面要做值的读取,先看一下时序图(分读取AD码值和读取寄存器值)

 

上面的两个时序图,左边的是读取码值,需要结合DRDY信号进行操作,右边的是读取寄存器的值,两个操作都是要在向ADS1256写入命令后等待t6后(最少50个clkin,大约6.5us)后进行操作。

 我们先根据发送8bit的方式写一个接收8bit的程序

 1 /**
 2  * @brief 接收8bit数据
 3  * 
 4  * @return uint8_t 
 5  */
 6 static uint8_t ADS1256_Recive8Bit(void)
 7 {
 8     uint8_t i;
 9     uint8_t read = 0;
10 
11     ADS1256_DelaySCLK();
12     /* ADS1256 要求 SCL高电平和低电平持续时间最小 200ns  */
13     for (i = 0; i < 8; i++)
14     {
15         SCK_0();
16         ADS1256_DelaySCLK();
17         read = read<<1;
18         SCK_1();
19         if (DO_IS_HIGH())
20         {
21             read++;
22         }
23         ADS1256_DelaySCLK();
24     }
25     return read;
26 }

流程很清楚,在一个8次的循环中根据判定DO的状态(MISO)生成数据,并且在一个循环体内操作时钟信号的震荡。

寄存器读取

然后就可以按照时序图完成读取1个寄存器的流程

 1 /**
 2  * @brief 读取寄存器
 3  * 
 4  * @param _RegID 寄存器地址
 5  * @return uint8_t 
 6  */
 7 static uint8_t ADS1256_ReadReg(uint8_t _RegID)
 8 {
 9     uint8_t read;
10     
11     CS_0();    /* SPI片选 = 0 */
12     ADS1256_Send8Bit(0x10 | _RegID);    /* 写寄存器的命令, 并发送寄存器地址 */
13     ADS1256_Send8Bit(0x00);    /* 寄存器个数 - 1, 此处读1个寄存器 */
14 
15     udelay(10);
16 
17     read = ADS1256_Recive8Bit();    /* 读寄存器值 */
18     CS_1();    /* SPI片选 = 1 */
19 
20     return read;
21 }

读取寄存器的指令格式如下:

 

8个bit中高4为位0x1,低4位是寄存器的地址。第12行的做了个与预算,将高4bit的读指令和低4bit的地址合并。读写寄存器指令后面有第二个byte是操作寄存器的个数。第13行发送的0000就是读取1个寄存器。

第15行我们等待了10us,然后进行读取操作。

我们可以通过读取STATE寄存器来获取IC的ID值,还是在GPIO初始化后面,调用读取函数

 

加载驱动文件,看看效果

 

STATE寄存器高4位是ID,默认值就是0x3。说明读取的过程也没有问题。

然后可以结合寄存器写入,测试一下是否工作正常

 

加载驱动模块

 

我们想配置寄存器写入0x13,然后读取这个寄存器,返回值为0x13,说明读写寄存器的流程都没问题。

其余操作

除了上面那些寄存器的读写什么的 ,还有一些其他常用的操作我把他拿出来封装成单独的程序,只需要调用就行了。

切换通道

ADS1256在每次输出数据前需要对MUX寄存器进行配置来选择通道。为了简化代码我们这里采用单端的形式来测量数据(但是貌似差分的流程差不多)。

 1 /**
 2  * @brief 通道切换
 3  * 
 4  * @param _ch 
 5  */
 6 static void ADS1256_SetChannal(uint8_t _ch)
 7 {
 8     if (_ch > 7)
 9     {
10         return;
11     }
12     ADS1256_WriteReg(REG_MUX, (_ch << 4) | (1 << 3));    /* Bit3 = 1, AINN 固定接 AINCOM */
13 }

因为ADS1256在单端模式下有8个通道,所以我们开始做个判定,当切换的通道值大于7就直接返回,配置的依据可以参考MUX寄存器定义

 

在单端模式下我们只用考虑高4位就可以。可以观察一下规律,通道几对应的值就是几,比如正端接的是AIN6,我们就将6左移4位然后把低4位的最高位置1就行了。

下面我们就可以根据手册来实现AD的读取了。

 

 

标签:读取,uint8,发送,MX6UL,寄存器,gpio,IC,ADS1256
From: https://www.cnblogs.com/yinsedeyinse/p/16974857.html

相关文章

  • 关于 'vue-cli-service' 不是内部或外部命令,也不是可运行的程序 或批处理文件 的处
    关于npmrunserve之后 'vue-cli-service'不是内部或外部命令,也不是可运行的程序或批处理文件一、安装node.js去官网安装Node.js(地址:https://nodejs.org/en/): ......
  • 如何不在main函数中访问Qapplication
    在学习qt的过程中,我们会慢慢的将主要代码在main函数外开发,这时可能会遇见不知道如何访问Qapplication的情况。比如,我们创建了MyWidget类,并在其中添加了一个按钮,我们希望按......
  • (摘抄)Defining Application Servers in IntelliJ IDEA
     ThisfeatureissupportedintheUltimateeditiononly.TodefineaserverinIntelliJIDEA,inmostofthecases,allyouhavetodoistospecifywherethec......
  • (转)jmeter 测试webservice
    地址:http://itindex.net/detail/45270-jmeter-webservice-%E6%B5%8B%E8%AF%95 1. BuildingaWebServiceTestPlan参考​​http://jmeter.apache.org/usermanual/build-w......
  • MagicAjax装配
    MagicAjax装配2007-09-1014:51(一)版本    下载:    ​​.NET1.1binaryrelease​​    ​​.NET2.0binaryr......
  • Statistical Signal Processing (UESTC)
    Teacher'semail:[email protected]熊文汇老师使用教材:由于是用英文教学,所以术语以及相关描述等都会使用英语。Inthislecture,wetalkabout2problemsdetectiona......
  • ICPC2022南京站游记
    第二次打南京了,去年是在南京拿的第一块铜(上海太卷了打了次铁)Day0南京站的热身赛真就万年不变,一直用那套袋鼠题。Day1开局我直接先敲板子,试图跟榜秒杀签到题,不久后\(I\)......
  • Mutable fields should not be "public static"
    https://stackoverflow.com/questions/53764748/mutable-fields-should-not-be-public-static protectedstaticList<String>COLUMN_NAMES=Collections.unmodifiabl......
  • earmusic任意文件读取漏洞[代码审计]
    怎么发现的,我也不懂啊。师傅怎么说,我跟着照做,毕竟技术不到位啊。功能点分析,反正这个下载的按钮可以存在漏洞。复现过程概述这个漏洞产生在用户端,首先去注册一个用户......
  • ICPC2022杭州站(补题)
    A-ModuloRuinstheLegend#include<bits/stdc++.h>#definelllonglongusingnamespacestd;lln,m,sum,n1,n2;llGcd(lla,llb){if(!b)returna;ret......