站内搜索
发作品签到
专业版

多功能模拟输出转接板4~20ma/0~5V

工程标签

2.3k
0
0
6

简介

8通道模拟输出4~20ma,可以通过短路帽选择电压输出0~5V,同时还包含测试代码。

简介:8通道模拟输出4~20ma,可以通过短路帽选择电压输出0~5V,同时还包含测试代码。

开源协议

GPL 3.0

(未经作者授权,禁止转载)
创建时间:2024-05-14 22:50:44更新时间:2024-05-15 09:50:54

描述

功能介绍

1.8通道模拟输出,工业标准信号(4~20ma/0~5V)

2.CAN芯片接口电路

3.24V电源控制

4.使用标准的9001-18481C00A接口,支持所有的单片机。

 

硬件说明:

1.模拟量输出电路

采用客益的GP8302-TC50-EW方案。

R59选择为2.5K,则全程范围内可以输出电流为0-20mA。
系统的散热通过Q13承担推荐使用SOP8封装的GL14P04-8,至少需要SOT89的封装。R58建议1206封装。

H7可以通过短路选择输出电流还是电压(不插短路帽表示输出电流)。

 

2.CAN芯片接口电路

CAN芯片采用SN65HVD230DR,电源电压支持3.3V

 

 

3.24V电源控制

其中VCC是3.3V VIN建议电压是24V。

两路电平都采用自恢复保险丝,进行短路保护。

 

 

软件说明:

GP8302是一个I2C信号转模拟信号转换器。主板卡采用GPIO模拟IIC,本转接板可以支持不同的单片机方案。

部分代码如下:

#define POWER_PIN    GET_PIN(C,8)
#define POWERCON_PIN GET_PIN(C,2)

const rt_base_t GP8302_SCLKS[] = { GET_PIN(B, 10), GET_PIN(E, 10), GET_PIN(B, 1), GET_PIN(B, 0), GET_PIN(D, 3), GET_PIN(
        D, 2), GET_PIN(A, 15), GET_PIN(C, 10) };
const rt_base_t GP8302_SDAS[] = { GET_PIN(E, 15), GET_PIN(E, 9), GET_PIN(E, 8), GET_PIN(D, 7), GET_PIN(D, 6), GET_PIN(D,
        1), GET_PIN(A, 8), GET_PIN(C, 11) };
const rt_base_t GP8302_ALARMS[] = { GET_PIN(E, 14), GET_PIN(E, 11), GET_PIN(E, 7), GET_PIN(B, 2), GET_PIN(D, 5),
        GET_PIN(D, 4), GET_PIN(A, 11), GET_PIN(A, 12) };

/**
 * The time delay function.
 *
 * @param microseconds.
 */
static void GP8302_udelay(rt_uint32_t us)
{
    rt_uint32_t ticks;
    rt_uint32_t told, tnow, tcnt = 0;
    rt_uint32_t reload = SysTick->LOAD;

    ticks = us * reload / (1000000 / RT_TICK_PER_SECOND);
    told = SysTick->VAL;
    while (1)
    {
        tnow = SysTick->VAL;
        if (tnow != told)
        {
            if (tnow < told)
            {
                tcnt += told - tnow;
            }
            else
            {
                tcnt += reload - tnow + told;
            }
            told = tnow;
            if (tcnt >= ticks)
            {
                break;
            }
        }
    }
}

//初始化IIC
static void IIC_Init(void)
{
    WRITE_REG16(CM_GPIO->PSPCR, 0x03);
    GPIO_SetFunc(GPIO_PORT_A, GPIO_PIN_15, GPIO_FUNC_0);
    for (uint8_t i = 0; i < (sizeof(GP8302_SCLKS) / sizeof(rt_base_t)); i++)
    {
        rt_pin_mode(GP8302_SCLKS[i], PIN_MODE_OUTPUT);
        rt_pin_write(GP8302_SCLKS[i], PIN_HIGH);
    }
    for (uint8_t i = 0; i < (sizeof(GP8302_SDAS) / sizeof(rt_base_t)); i++)
    {
        rt_pin_mode(GP8302_SDAS[i], PIN_MODE_OUTPUT);
        rt_pin_write(GP8302_SDAS[i], PIN_HIGH);
    }
    for (uint8_t i = 0; i < (sizeof(GP8302_ALARMS) / sizeof(rt_base_t)); i++)
    {
        rt_pin_mode(GP8302_ALARMS[i], PIN_MODE_INPUT);
    }
    rt_pin_mode(POWER_PIN, PIN_MODE_OUTPUT);
    rt_pin_mode(POWERCON_PIN, PIN_MODE_INPUT);
}

//产生IIC起始信号     SCL在高电平时,SDA由高变低
static void IIC_Start(uint8_t channelNum)
{
    rt_pin_mode(GP8302_SDAS[channelNum], PIN_MODE_OUTPUT);
    GP8302_udelay(2);
    rt_pin_write(GP8302_SDAS[channelNum], PIN_HIGH);
    GP8302_udelay(2);
    rt_pin_write(GP8302_SCLKS[channelNum], PIN_HIGH);
    GP8302_udelay(2);
    rt_pin_write(GP8302_SDAS[channelNum], PIN_LOW);
    GP8302_udelay(2);
    rt_pin_write(GP8302_SCLKS[channelNum], PIN_LOW);
    GP8302_udelay(2);
}

//产生IIC停止信号     SCL在高电平时,SDA由低变高
static void IIC_Stop(uint8_t channelNum)
{
    rt_pin_mode(GP8302_SDAS[channelNum], PIN_MODE_OUTPUT);
    GP8302_udelay(2);
    rt_pin_write(GP8302_SDAS[channelNum], PIN_LOW);
    GP8302_udelay(2);
    rt_pin_write(GP8302_SCLKS[channelNum], PIN_HIGH);
    GP8302_udelay(2);
    rt_pin_write(GP8302_SDAS[channelNum], PIN_HIGH);
    GP8302_udelay(2);
}

//等待应答信号到来,SCL在高电平时,SDA为低电平则接受应答成功
//返回值:  1,接收应答失败
//          0,接收应答成功
static uint8_t IIC_Wait_Ack(uint8_t channelNum)                                     //发送一个数据之后,从机必须产生应答,如果没应答,代表数据传输失败
{
    uint8_t ucErrTime = 0;
    rt_pin_write(GP8302_SDAS[channelNum], PIN_HIGH);
    GP8302_udelay(2);
    rt_pin_write(GP8302_SCLKS[channelNum], PIN_HIGH);
    GP8302_udelay(2);             //SCL在高电平时,SDA为低电平则接受应答成功
    rt_pin_mode(GP8302_SDAS[channelNum], PIN_MODE_INPUT);
    GP8302_udelay(2);
    while (rt_pin_read(GP8302_SDAS[channelNum]))                                     //如果返回1,则接受失败
    {
        ucErrTime++;
        if (ucErrTime > 250)                                                           //如果扫描250次后仍无应答
        {
            IIC_Stop(channelNum);                                                   //发送停止信号
            return 1;
        }
        GP8302_udelay(1);
    }
    rt_pin_write(GP8302_SCLKS[channelNum], PIN_LOW);                                //时钟输出0
    GP8302_udelay(2);
    return 0;
}

//产生ACK应答           在SCL时钟由低变高之前将SDA拉低,并保持至SCL由高变低时
static void IIC_Ack(uint8_t channelNum)
{
    rt_pin_mode(GP8302_SDAS[channelNum], PIN_MODE_OUTPUT);
    GP8302_udelay(2);
    rt_pin_write(GP8302_SCLKS[channelNum], PIN_LOW);
    GP8302_udelay(2);
    rt_pin_write(GP8302_SDAS[channelNum], PIN_LOW);
    GP8302_udelay(2);
    rt_pin_write(GP8302_SCLKS[channelNum], PIN_HIGH);
    GP8302_udelay(2);
    rt_pin_write(GP8302_SCLKS[channelNum], PIN_LOW);
    GP8302_udelay(2);

}

//不产生ACK应答         在SCL时钟由低变高之前将SDA拉高,并保持至SCL由高变低时
static void IIC_NAck(uint8_t channelNum)
{
    rt_pin_mode(GP8302_SDAS[channelNum], PIN_MODE_OUTPUT);
    GP8302_udelay(2);
    rt_pin_write(GP8302_SCLKS[channelNum], PIN_LOW);
    GP8302_udelay(2);
    rt_pin_write(GP8302_SDAS[channelNum], PIN_HIGH);
    GP8302_udelay(2);
    rt_pin_write(GP8302_SCLKS[channelNum], PIN_HIGH);
    GP8302_udelay(2);
    rt_pin_write(GP8302_SCLKS[channelNum], PIN_LOW);
    GP8302_udelay(2);
}

//IIC发送一个字节     从高位开始传输,数据传输时,SDA在SCL由低→高→低时不允许变化
//返回从机有无应答
//1,有应答
//0,无应答
static void IIC_Write_Byte(uint8_t Byte, uint8_t channelNum)
{
    uint8_t i;
    rt_pin_mode(GP8302_SDAS[channelNum], PIN_MODE_OUTPUT);
    GP8302_udelay(2);
    rt_pin_write(GP8302_SCLKS[channelNum], PIN_LOW);                                //拉低时钟开始数据传输
    GP8302_udelay(2);
    for (i = 0; i < 8; i++)
    {
        if (Byte & (0X80 >> i))
            rt_pin_write(GP8302_SDAS[channelNum], PIN_HIGH);
        else
            rt_pin_write(GP8302_SDAS[channelNum], PIN_LOW);
        GP8302_udelay(2);
        rt_pin_write(GP8302_SCLKS[channelNum], PIN_HIGH);
        GP8302_udelay(2);
        rt_pin_write(GP8302_SCLKS[channelNum], PIN_LOW);
    }
}

 

//写入数据时序:
//开始信号 -- 器件地址+写命令 -- 等待应答 -- 写入存储地址 -- 等待应答 --
//写入数据 -- 等待应答 -- 停止信号
static void IIC_Write_Data(uint8_t DataAddr, uint8_t DeviceAddr, uint16_t Data, uint8_t channelNum)
{
    IIC_Start(channelNum);
    //IIC_Write_Byte(DeviceAddr | 0xA0,channelNum);
    IIC_Write_Byte(0xB0, channelNum);
    IIC_Wait_Ack(channelNum);
    //IIC_Write_Byte(DataAddr,channelNum);
    IIC_Write_Byte(0x02, channelNum);
    IIC_Wait_Ack(channelNum);
    IIC_Write_Byte(((Data & 0x0f) << 4), channelNum);
    IIC_Wait_Ack(channelNum);
    IIC_Write_Byte(Data >> 4, channelNum);
    IIC_Wait_Ack(channelNum);
    IIC_Stop(channelNum);
    GP8302_udelay(1000);    
}

const uint16_t channel10mAValue[] = { 2056, 2060, 2055, 2044, 2058, 2058, 2050, 2058 };

const uint16_t channel15mAValue[] = { 3080, 3080, 3080, 3071, 3080, 3085, 3073, 3078 };

const uint16_t channel2v5Value[] = { 2068, 2068, 2068, 2062, 2068, 2068, 2062, 2068 };

const uint16_t channel3v75Value[] = { 3098, 3098, 3098, 3090, 3100, 3100, 3090, 3100 };

static void cmd(int argc, char**argv)
{
    if (argc < 2)
    {
        rt_kprintf("Please input'cmd <channel step>'\n");
        return;
    }
        uint8_t channelNum = argv[1][0] - 0x30;
        uint8_t testStep = argv[2][0] - 0x30;
        if (channelNum <= 7 && testStep <= 4)
        {
            if (testStep == 0)
            {
                IIC_Write_Data(0, 0, 0, channelNum);
            }
            else if (testStep == 1)
            {
                IIC_Write_Data(0, 0, channel10mAValue[channelNum], channelNum);
            }
            else if (testStep == 2)
            {
                IIC_Write_Data(0, 0, channel15mAValue[channelNum], channelNum);
            }
            else if (testStep == 3)
            {
                IIC_Write_Data(0, 0, channel2v5Value[channelNum], channelNum);
            }
            else if (testStep == 4)
            {
                IIC_Write_Data(0, 0, channel3v75Value[channelNum], channelNum);
            }
            rt_kprintf("%d %d ok\n", channelNum, testStep);
        }
        else
        {
            rt_kprintf("channel num <=7 || step <= 4\n");
        }
}


实物展示

 

演示视频(10ma 15ma)

 

设计图

未生成预览图,请在编辑器重新保存一次

BOM

暂无BOM

3D模型

序号文件名称下载次数
暂无数据

附件

序号文件名称下载次数
1
多功能模拟输出转接板.mp4
7
克隆工程
添加到专辑
0
0
分享
侵权投诉

评论

全部评论(1
按时间排序|按热度排序
粉丝0|获赞0
相关工程
暂无相关工程

底部导航