注明:文章转载于知乎专栏“单片机嵌入式软件开发经验分享”

看完文章的感受:能够根据某款单片机型号的数据手册,对各大常用模块比如GPIO设置、定时器、SPI、UART、IIC等等进行封装,本身一方面C语言比较熟练了,另外单片机项目也经历过或者说对某型号单片机熟悉的前提下,为了后续代码的可移植性、代码可阅读性等更高层次的追求而做的工作。若有接触过SMT32,根据数据手册对各大模块进行封装,本质上就是对相关寄存器的设置,封装好后的代码就是STM32的库文件,具体项目开发用官方的库文件更容易上手,建议库文件和寄存器操作都去关注,这也是学习ST工程师封装思想及C代码编程非常好的例程。刚接触单片机,目的就是能根据数据手册实现各模块功能,进而实现自己项目所需的功能就可以了,当然封装思想是进阶要求。

作为一个优秀的嵌入式软件开发工程师,必须要熟读厂家提供的芯片手册,因为原因很简单,“这个世界上没有一个人比开发者更了解设备”。笔者不止一次被网络上的答案坑过了,所以很难再像新手一样,遇到设备问题第一件事百度。所以笔者也建议,一定要读原版英文手册,这样可以提高开发效率,降低自己犯错的概率。

2、阅读芯片手册

本文希望与读者一起学习探讨TI提供的芯片手册《msp430x4x user guide》

芯片手册

在选型过程中,我们认识到MSP430F4系列单片机拥有SD16功能模块,于是直接翻到介绍SD16的模块。

下面的内容是笔者在阅读的时候记录下来的学习笔记,可以跳过去,这只是以MSP430F4单片机的AD模块为例,从官方数据手册中得到关键信息(官方文件肯定是英文,阅读时需要耐心,毕竟官方数据手册是编程的根源)。

工作目标:创建sd16_dri.c/.h文件 封装SD16系列功能
1 SD16介绍数据手册原文:The SD16 module consists of up to three independent sigma-delta analog-to-digital converters and an internal voltage reference. Each channel has up to 8 fully differential multiplexed analog input pairs including a built-in temperature sensor. The converters are based on second-order oversampling sigma-delta modulators and digital decimation filters. The decimation filters are comb type filters with selectable oversampling ratios of up to 256. Additional filtering can be done in software.中文翻译:SD16模块包含三个独立的sigma-delta模数转换器,和一个内部电压参考源,每一路AD转换器最多可以有八路不同的差分模拟输入,包括一个温度传感器。转换器包含二阶采样sigma-delta调制器和一个数字滤波器,数字滤波器可由一个最高256的参数来调整。Featuresof the SD16 include:·16-bit sigma-delta architecture ·Up to three independent, simultaneously sampling ADC channels (The number of channels is device dependent, see the device-specific data sheet.)·Up to eight multiplexed differential analog inputs per channel(The number of inputs is device dependent, see the device-specific data sheet.)·Software selectable on-chip reference voltage generation (1.2 V)·Software selectable internal or external reference·Built-in temperature sensor accessible by all channels·Up to 1.048576-MHz modulator input frequency·Selectable low-power conversion modeThe block diagram of the SD16 module is shown in Figure 29−1.SD16的特性包括16位的sigma-delta结构最高三个独立的,同时的,采样ADC频道。每个通道最多8路差分输入软件可选的内部电压基准1.2V软件可选是否使用外部基准源温度传感器可以被使用输入的时钟频率最高可达1.04MHZ可选的低功耗模式SD16控制电路模块包含三个部分 ① 时钟的分频电路 ② 基准源选择(内部还是外部) ③ 温度传感器输出
单片机代码封装思想——根据数据手册

单片机代码封装思想——根据数据手册

一个ADC对应可用八个通道MSP430F425A有三个ADC,分别使用了他们的第一个通道。该模块分为几个部分 ①八个模拟通道选择模块A1.0- A1.7选择,通过SD16INCHx选择 ②模拟输入通道公用一个增益器 SD16GAINx ③数字滤波器模块数字输出模块 SD16LP SD16OSR ④模式运行模式选择电路 SD16GRP SD16SC SD16SNGL,主要配置不同通道与转换器运行时间关系。 ⑤最终存放AD数据的寄存器电路 SD16MEM129.2SD16 OperationThe SD16 module is configured with user software. The setup and operation of the SD16 is discussed in the following sections.29.2.1ADC CoreThe analog-to-digital conversion is performed by a 1-bit, second-order sigma-delta modulator. A single-bit comparator within the modulator quantizes the input signal with the modulator frequency f M . The resulting 1-bit data stream is averaged by the digital filter for the conversion result.29.2.2Analog Input Range and PGAThe full-scale input voltage range for each analog input pair is dependent on the gain setting of the programmable gain amplifier of each channel. Themaximum full-scale range is ±V FSR where V FSR is defined by:For a 1.2V reference, the maximum full-scale input range for a gain of 1 is:refer to the device-specific data sheet for full-scale input specifications.SD16操作 通过单片机编程配置SD16ADC的核心1位二阶sigma-delta 调幅器单位比较数字转化,数据被平均滤波。最大模拟输入电压范围是由可编程的增益器决定的,最大可输入电压由VREF和增益GAIN决定,内部基准电压是1.2V。29.2.3Voltage Reference GeneratorThe SD16 module has a built-in 1.2V reference that can be used for each SD16 channel and is enabled by the SD16REFON bit. When using the internal reference an external 100nF capacitor connected from V REF to AV SS is recommended to reduce noise. The internal reference voltage can be used off-chip when SD16VMIDON = 1. The buffered output can provide up to 1mA of drive. When using the internal reference off-chip, a 470nF capacitor connected from V REF to AV SS is required. See device-specific data sheet for parameters. An external voltage reference can be applied to the V REF input when SD16REFONand SD16VMIDON are both reset.29.2.4Auto Power-DownThe SD16 is designed for low power applications. When the SD16 is not actively converting, it is automatically disabled and automatically re-enabled when a conversion is started. The reference is not automatically disabled,but can be disabled by setting SD16REFON = 0. When the SD16 or reference are disabled, they consume no current.内部基准电压产生器内部存在一个1.2V的基准电压发生器,使能通过SD16REFON位打开当使用外部基准的时候,参考一个外部的100nf电容加在VREF和AVSS中间可以有效的减缓噪声,内部基准可以给外部使用,最多出1mA电流。当使用内部基准给外部用的时候,加入470nF是推荐电路。通过SD16REFON和SD16VMIDON配置是否使用外部基准。自动低功耗SD16为低功耗而生。当SD16不处于活跃状态,自动失能。内部基准电压,在需要低功耗的时候手动关闭和打开,不提供自动功能。29.2.5Analog Input Pair Selection Each SD16 channel can convert up to 8 differential input pairs multiplexedinto the PGA. Up to six input pairs (A0-A5) are available externally on the device.See the device-specific data sheet for analog input pin information. An internal temperature sensor is available to each channel using the A6 multiplexer input.Input A7 is a shorted connection between the + and − input pair and can be used to calibrate the offset of each SD16 input stage. Note that the measured offset depends on the impedance of the external circuitry; thus, the actual offset seen at any of the analog inputs may be different. Analog Input SetupThe analog input of each channel is configured using the SD16INCTLx register. These settings can be independently configured for each SD16 channel. The SD16INCHx bits select one of eight differential input pairs of the analog multiplexer.The gain for each PGA is selected by the SD16GAINx bits. A total of six gain settings are available.During conversion any modification to the SD16INCHx and SD16GAINx bits will become effective with the next decimation step of the digital filter.After these bits are modified, the next three conversions may be invalid due to the settling time of the digital filter. 模拟输入对模块每一个AD可以最多扩展到8个通道,这八个通道是独立的差分输入对,但共享一个PGA,八个通道当中A0-A5是可以被外部使用的。每一个系列的芯片,他的AD数量不同,每一个AD的通道数量也不同。一个内部的温度传感器可以被使用,任何一个内部AD可以使用A6通道,去访问温度传感器数据。A7输入时短路链接在+-输入对中,是用来校正输入offset,测量OFFSET由外部电路输入阻抗决定,因此实际的OFFSET会不同。模拟输入设置每一个ADC使用SD16INCTLx寄存器来配置,是独立的寄存器配置。使用SD16INCHx寄存器来选择八个通道,使用哪一个通道与ADC模块进行连接。SD16GAIN寄存器决定了增益PGA的增益程度。在转换期间任何修改 SD16INCHx和SD16GAIN将会变得有效在下一个数字滤波期间。SD16INTDLY寄存器决定了,修改寄存器是否快速作用的问题。如果SD16INTDLY= 0 则快速作用。

笔者在做两件事

1、翻译英文原文

2、查找重点内容,重点特性,思考每个寄存器的作用。

做完这两件事,反复倒嚼后,再去读每个寄存器对应的含义。

至此写封装驱动的准备就做好了,我明白了,ADC转换的几种模式,以及ADC转换结果储存的位置,以及采样频率,采样滤波等等信息。

单片机代码封装思想——根据数据手册

3、编写封装代码

在编写封装代码之前,我首先会站在用户的角度,提出我希望的功能。

1、我希望能快速的,含义明确的初始化SD16设备

2、我希望快捷的读取SD16的数据

3、其他乱七八糟的特性我不在乎,我不想看到

根据这个需要求,我提出了两个API函数

/**MSP430F425A sd16 driver version v1.0* author : Jingyan Chen @ Wotian 2017.10.30** access operation is* · config as one channle one shot mode* · config as one channle continue mode* · basic config function* need to update function* · Conversion Operation Using Preload* · Group of Channels, Continuous Conversion* · Group of Channels, Single Conversion** Note : msp430f425A each ADC have only one Channel A0.0 A1.0 A2.0* channel is default seleted as channel 0 in this driver*/void csp_sd16_init(void);//外部一旦调用此函数,那么缺省设置将会被配置SD16被配置在连续工作模式下uint16_t read_conver_result(uint8_t channel_id);//读取 channel_id号ADC转换结果,结果是返回值

我在API中提供了一个缺省init函数,init后设备处于一种已经在工作的状态,外部不再需要配置;提供了一个获得SD16值的方法,直接返回所需值。

在我们看如何实现之前,笔者想推荐一个特别好用语法,那就是enum(枚举)

举例:

作者意识到了ADC的时钟源选择包含四种

分别是

MCLK=0,对应寄存器值是00

SMCLK,对应寄存器值是01

ACLK,对应寄存器值是10

TACLK, 对应寄存器值是11

思考如下

往 SSD16CTL寄存器的BIT4 BIT5 放入 00 则选择MCLK为SD16的时钟,如果写01 则是SMCLK,写10则是ACLK,依次类推。

我希望实际写入的寄存器值与MCLK等字符串建立联系。那么如何建立联系呢?

枚举的意义就来了!

请看代码

typedef enum{MCLK=0,SMCLK,ACLK,TACLK,}clk_sel_t;typedef struct{clk_sel_t clk_sel;clk_div_t clk_div;v_ref_sel_t v_ref_sel;}sd16_reg_t;sd16_reg_t sd16_reg;void set_clk_as_ACLK(void){sd16_reg.clk_sel = ACLK;SD16CTL |= (sd16_reg.clk_sel << 4) ;}

请读者举一反三,如果我想设置时钟为TACLK

是不是写

sd16_reg.clk_sel = TACLK;SD16CTL |= (sd16_reg.clk_sel << 4) ;

就行了?

枚举关联了实际意义字符串和正确的寄存器配置方法对应BIT值,非常好用!

于是作者的封装代码分为两步

1、构造结构体数据

2、作用结构体数据

这部分原作者列举了他对AD模块封装的结构体,有兴趣的可以去看看。这篇文章很长了,封装SD16的框架在这篇文章里面已经提及了,至于进一步如何去写,如何去做,放在下一篇文章中提到。

作者思考

笔者听着音乐,看起来一天的工作并没有让我疲乏。笔者希望能够帮助别人,把自己的一些思考分享给别人。笔者不喜欢大段大段的帖自己的代码,因为笔者在读别人的文章的时候,代码部分都是完全跳过的,因为每个人都有自己的写代码习惯,没人愿意读别人的代码,但是我愿意和他人分享我的思路,我的学习方法,若是有益那是极好,若是无益,那就关掉它,看会狗血浪漫的爱情剧呗!

相关文章