• 第37章_瑞萨MCU零基础入门系列教程之DAC数模转换模块


    本教程基于韦东山百问网出的 DShanMCU-RA6M5开发板 进行编写,需要的同学可以在这里获取: https://item.taobao.com/item.htm?id=728461040949

    配套资料获取:https://renesas-docs.100ask.net

    瑞萨MCU零基础入门系列教程汇总https://blog.csdn.net/qq_35181236/article/details/132779862


    第37章 DAC数模转换模块

    37.1 SPI-DAC模块工作原理

    本次实验使用的SPI-DAC模块是定制模块,原理图如下图所示:

    核心芯片是TLC5615,主机通过SPI接口发出一个数字量,TCL5615将数字量转化为模拟量,并通过OUT引脚输出模拟电压来点亮LED。通过LED的亮度形象地感受DAC的效果。这个模块的参考电压是2.048V,可以输出的最大电压是2倍参考电压,即4.096V。

    TLC5615是一个10bit的DAC转换芯片,用户需要将需要转换的数字量左移2bit后再通过SPI发送给TLC5165,数据格式和转换关系如下图所示:

    由于TLC5615是10位DAC,它允许主控每次发送12位或者16位的数据,12位和16位的发送数据格式要求如下图所示。

    这个模块的使用比较简单,重点是在SPI的通信上,其次是在发送数据的时候需要移位。

    37.2 模块配置

    本次实验使用的是开发板配套扩展板的SPI组,如下图所示:

    使用的SPI引脚是P202/P203/P204和P205,SPI引脚对应使用的是RA6M5的Common SPI0:

    本次实验使用的SPI-DAC模块控制比较简单,对于SPI的Stack配置使用默认参数即可,使能发送buffer空中断,配置中断对调函数,如下图所示:

    37.3 外设驱动

    37.3.1 GPIO驱动

    本次实验的SPI片选信号脚为P205,它的驱动如下:

    static struct IODev gSPIDACCSDev = {
        .name = "SPIDAC CS",
        .port = BSP_IO_PORT_02_PIN_05,
        .Init = IODrvInit,
        .Read = IODrvRead,
        .Write = IODrvWrite,
        .next = NULL
    };
    
    void IODevicesCreate(void)
    {
        IODeviceInsert(&gSPIDACCSDev);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    对于GPIO的驱动函数参考《32.4.1 GPIO驱动》。

    37.3.2 SPI驱动

    参考《35.4.2 SPI驱动》。

    37.4 DAC驱动程序

    37.4.1 SPI-DAC设备对象封装

    要操纵SPI-DAC模块,只需要初始化、写入数值。为了更具观赏性,还可以提供写入多个数值的操作。把这些特性封装为一个结构体,代码如下(dev_spi_dac.h):

    typedef struct SPIDACDev{
        char *name;
        int (*Init)(struct SPIDACDev *ptdev);
        int (*SetValue)(struct SPIDACDev *ptdev, float voltage);
        int (*Write)(struct SPIDACDev *ptdev, unsigned char *buf, unsigned int length);
    }SPIDACDevice;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    然后在dev_spi_dac.c里构造一个SPIDACDevice结构体,并给上层代码提高获得这个结构体的函数,代码如下:

    static SPIDACDevice gDAC = {
        .name = "SPI DAC",
        .Init       = SPIDACDevInit,
        .SetValue   = SPIDACDevSetValue,
        .Write      = SPIDACDevWrite,
    };
    
    struct SPIDACDev *SPIDACGetDevice(void)
    {
        return &gDAC;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    37.4.2 初始化SPI-DAC

    初始化SPI-DAC模块,本质就是初始化SPI控制器,代码如下:

    static int SPIDACDevInit (struct SPIDACDev *ptdev)
    {
        if(NULL == ptdev)   return -EINVAL;
        gSPI = SPIDeviceFind("SPIDAC SPI");
        if(NULL == gSPI)    return -ENODEV;
        if(ESUCCESS != gSPI->Init(gSPI))    return -EIO;
        return ESUCCESS;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    37.4.3 输出一个模拟量

    要输出指定数字量,需要根据TLC5615的数据格式进行移位计算,再通过SPI发送给TLC5615:

    static int SPIDACDevSetValue (struct SPIDACDev *ptdev, float voltage)
    {
        if(NULL == ptdev)   return -EINVAL;
        if(NULL == gSPI)    return -EINVAL;
        if(DAC_OUT_MAX_VOLTAGE < voltage)     return -EINVAL;
    
        unsigned short value = (unsigned short)((voltage*1024)/(DAC_OUT_MAX_VOLTAGE));
        value = (unsigned short)(value<<2);
        return gSPI->Write(gSPI, (unsigned char*)&value, 2);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    37.4.4 输出N个模拟量

    为了方便用户使用,将N个数字量在模块驱动函数内部进行格式转换,然后再通过SPI传输给转换芯片:

    static int SPIDACDevWrite(struct SPIDACDev *ptdev, unsigned char *buf, unsigned int length)
    {
        if(NULL == ptdev)   return -EINVAL;
        if(NULL == gSPI)    return -EINVAL;
        if(NULL == buf)     return -EINVAL;
        if(0 == length)     return -EINVAL;
        
        unsigned short *pbuf = (unsigned short*)buf;
        for(unsigned int i=0; iWrite(gSPI, buf, length);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    37.5 测试程序

    本次实验使用SPI传输,连续发送0~4V的电压给DAC模块,以实现呼吸灯效果:

    void DeviceTest(void)
    {
        UartDevicesRegister();
        TimerDevicesRegister();
        SPIDevicesRegister();
        IODevicesRegister();
        
        SPIDACDevice *pDevice = SPIDACGetDevice();
        if(NULL == pDevice)
        {
            xprintf("Failed to Find SPI DAC Devide!\r\n");
            return;
        }
        pDevice->Init(pDevice);
        
        bool dir = false;
        volatile float value = 0;
        while(1)
        {
            if(value > 4)
                dir = true;
            else if(value < 0)
                dir = false;
            
            if(dir)
                value += (float)0.5;
            else
                value -= (float)0.5;
            pDevice->SetValue(pDevice, value);
            mdelay(300);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    37.6 测试结果

    将SPI-DAC模块插入到扩展板上后,再将程序烧写到开发板上运行,用户可以看到SPI-DAC模块上的LED呈现呼吸灯效果。


    本章完
  • 相关阅读:
    Visual Studio 2019下编译OpenCV 4.7 与OpenCV 4.7 contrib
    操作系统面试题
    解决Windows 10 家庭中文版没有组策略编辑器的问题
    Java 中的全部锁
    【数据结构与算法】用队列实现栈&&用栈实现队列&&设计循环队列
    【毕业设计】基于单片机的家庭智能监控系统 - 物联网 stm32 嵌入式
    PID整定方法
    map和set模拟实现
    分布式对象池用哪些组件
    把Android手机变成电脑摄像头
  • 原文地址:https://blog.csdn.net/qq_35181236/article/details/132891963