【GD32F427开发板试用】1、双路高精度ADC转换芯片采集电压电流数据

本篇文章来自极术社区与兆易创新组织的GD32F427开发板评测活动,更多开发板试用活动请关注极术社区网站。作者:Phoenix_dz9WiU

CS1180是高精度、低功耗模数转换芯片。其分辨率为 20bit,有效分辨率可达 19 位。可以广泛使用在工艺控制、量重、液体/气体化学分析、血液分析、智能发送器、便携测量仪器领域。
本次主要以智能变送器为主 采集电压电流值稳控
首先我们看一下管脚说明

主要以spi通信方式为主,我这里是用到两个adc芯片 SDI、SDO、SCLK、三线共用,以片选不同采集不同路的数据
接下来看规格书要求的通信时序

按照要求编写即可

接下来就是我们要操作的寄存器 以下是主要寄存器

SETUP和MUX在初始化中配置,增益倍数选择,默认是0,测试中4倍也是可以读到的

这里要注意ACR寄存器使用单极性输出,时钟选择/256,这个要根据你的时钟选择判断,转换范围选择也要选择VERF/2的,是有哪位我的外部电路输入电压不同导致选择的不同 其他位用默认值0即可

ODAC寄存器配置为0x30,这里我也没有特别理解,网上搜到的驱动是这样写的,可能与你本身的硬件电路有关,我买的是cs1180集成板,里面电路已经确定的,如果各位知道原因的话,也教一下我,谢谢
主要的内容就是以上,接下来直接看代码,如有疑问和问题,敬请指出

`
//寄存器地址定义

define SETUP 0X00//PGA 及BO//cs 控制

define MUX 0X01//输入通道选择

define ACR 0X02//模拟电路控制

define ODAC 0X03//Offset DAC 设置

define DIO 0X04//数字I/O 引脚设置

define DIR 0X05//输入输出的方向选择

define IOCON 0X06//I/O 配置寄存器

define OCC0 0X07//失调误差正系数

define OCC1 0X08//失调误差正系数

define OCC2 0X09//失调误差正系数

define GCC0 0X0A//增益误差校正系数

define GCC1 0X0B//增益误差校正系数

define GCC2 0X0C//增益误差校正系数

define DOR2 0X0D//模数转换数据高8位

define DOR1 0X0E//模数转换数据中8位

define DOR0 0X0F//模数转换数据低8位

//命令定义

define RDATA 0X01//从DOR 寄存器中读取数据

define RDATAC 0X03//从DOR 寄存器中连续读取数据

define STOPC 0X0F//停止从DOR 寄存器中连续读取数据

define RREG 0X10//低4位为寄存器地址

define WREG 0X50//低4位为寄存器地址

define CALSELF 0XF0//对芯片的失调误差和增益误差进行纠正

define OCALSELF 0XF1//对芯片的失调误差进行纠正

define GCALSELF 0XF2//对芯片的增益误差进行纠正

define OCALSYS 0XF3//对系统的失调误差进行纠正

define GCALSYS 0XF4//对系统的增益误差进行纠正

define WAKEUP 0XFB//将系统从睡眠模式模式中唤醒

define SYNC 0XFC//对DRDY 进行同步

define SLEEP 0XFD//使芯片进入睡眠模式

define RESET 0XFE//将芯片复位到上电后的状态

define P_ADD 0XA3//将芯片复位到上电后的状态

define SPI_SDI(n) (n?gpio_bit_set(GPIOA, GPIO_PIN_6):gpio_bit_reset(GPIOA, GPIO_PIN_6))

define SPI_SCK(n) (n?gpio_bit_set(GPIOA, GPIO_PIN_0):gpio_bit_reset(GPIOA, GPIO_PIN_0))

define SPI_SDO_READ() gpio_input_bit_get(GPIOA,GPIO_PIN_5)

define VOL_EXTI_LINE EXTI_4

define CURR_EXTI_LINE EXTI_5

unsigned long curr_adc,vol_adc;
void ADC_GPIO_init()
{

//IO口定义
rcu_periph_clock_enable(RCU_GPIOA);
rcu_periph_clock_enable(RCU_GPIOC);
//SCK
gpio_mode_set(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_0);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_0);
//SDO
gpio_mode_set(GPIOA, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN_1);

//SDI
gpio_mode_set(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_6);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_6);
//CS_A
gpio_mode_set(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_7);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_7);
//CS_V
gpio_mode_set(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_7);
gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_7);
//DRDY2 电压
gpio_mode_set(GPIOC, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN_4);
//DRDY1 电流
gpio_mode_set(GPIOC, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN_5);


/* connect EXTI line to GPIO pin */
syscfg_exti_line_config(EXTI_SOURCE_GPIOC, EXTI_SOURCE_PIN4);
syscfg_exti_line_config(EXTI_SOURCE_GPIOC, EXTI_SOURCE_PIN5);

/* configure EXTI line */
exti_init(EXTI_4, EXTI_INTERRUPT, EXTI_TRIG_FALLING);
exti_interrupt_flag_clear(EXTI_4);

exti_init(EXTI_5, EXTI_INTERRUPT, EXTI_TRIG_FALLING);
exti_interrupt_flag_clear(EXTI_5);

}

/写一个字节的数据到CS1180的SDI引脚/
void Write_One_Byte(unsigned char Byte)
{

char i=0;
    SPI_SCK(1);
for(;i<8;i++)
{
    
    if(Byte&(0x80>>i))           //先传高位  
    {
        SPI_SDI(1);
    }
    else
    {
        SPI_SDI(0);
    }
    Delay1us();
    SPI_SCK(0);                               //写数据的时候,数据在上升沿被写入   
    Delay1us();
    SPI_SCK(1);
    Delay1us();
}

}

/从SDO引脚读取一个字节的数据/
unsigned char Read_One_Byte(void)
{

char i=0;
unsigned char Data = 0;
SPI_SCK(1);
for(;i<8;i++)
{            //读数据的时候,数据在下降沿被输出
            
    SPI_SCK(0);
    Delay1us();
    Data = (Data << 1) | SPI_SDO_READ();
    Delay1us();
    SPI_SCK(1);
    Delay1us();
}
return Data;

}

/1:读取ADC数据 命令编码:0x01/
unsigned long Read_Adc_Data(void)
{

//unsigned char datah,datam,datal;
    unsigned long datah;
    unsigned long datam,datal;
unsigned long c=0;
datal=datam=datah=0;

Write_One_Byte(0x01);         //写入命令:0x01 写完后SCK=1 

Delay1us();
datah=Read_One_Byte();
datam=Read_One_Byte();
datal=Read_One_Byte();
c=datah<<8|datam;

return(c);

}

if 0 //此段没有用到 暂未验证 感兴趣的可以加上尝试

/2:读取寄存器的值 命令编码:0001 rrrr xxxx nnnn/
/_void Read_Reg_Data(char start_reg_addr,char num,char_ptr)
{

Write_One_Byte(0x10|start_reg_addr);  //命令的第一个字节    
Write_One_Byte(num-1);
for(;num!=0;num--)
{
    *(ptr++) = Read_One_Byte();           //将读取的寄存器的值顺序保存在数组中 
}

}
*/
/3:写数据到控制寄存器中 命令编码:0101 rrrr xxxx nnnn/
unsigned char Write_Reg_Data(char start_reg_addr,char reg_data)
{

char err_num = 0;
Write_One_Byte(0x50|start_reg_addr);  //命令的第一个字节,第一个寄存器为0x00   
Write_One_Byte(0x00);                 //命令的第二个字节,总共写1个寄存器   
Write_One_Byte(reg_data);             //写入第一个寄存器值  
return 0;

}

endif

//4:CS1180初始化函数
void CS1180_ADC_Init(void)
{

//初始化电流ADC 
ADC_GPIO_init();
gpio_bit_reset(GPIOA, GPIO_PIN_7);  //开电流片选 关电压
gpio_bit_set(GPIOC, GPIO_PIN_7);
Write_One_Byte(RESET);   
    Delay1us();
    Write_Reg_Data(SETUP,0x00);     // 128x  PGA
Write_Reg_Data(ACR,0x62);
Write_Reg_Data(ODAC,0x30);
    delay_ms(5);
    while(DRDY1 == 1);
    Read_One_Byte();
    delay_ms(5);
gpio_bit_set(GPIOA, GPIO_PIN_7);
//初始化电压ADC   
gpio_bit_set(GPIOC, GPIO_PIN_7);  
gpio_bit_reset(GPIOA, GPIO_PIN_7);//关电流片选 开电压
Write_One_Byte(RESET);   
Delay1us();
Write_Reg_Data(SETUP,0x00);     // 128x  PGA
Write_Reg_Data(ACR,0x62);
Write_Reg_Data(ODAC,0x30);
delay_ms(5);
while(DRDY2 == 1);
Read_One_Byte();
delay_ms(5);
delay_ms(5);
gpio_bit_set(GPIOC, GPIO_PIN_7); 

//外部中断初始化
nvic_irq_enable(EXTI4_IRQn, 2U, 0U);    //电压
nvic_irq_enable(EXTI5_9_IRQn, 1U, 0U);    //电流

}

/外部中断0响应函数 读取电压/
void EXTI5_9_IRQHandler(void)
{

if (RESET != exti_interrupt_flag_get(VOL_EXTI_LINE)) {
    nvic_irq_disable(EXTI5_9_IRQn);//关掉电流表中断 
    exti_interrupt_flag_clear(VOL_EXTI_LINE);
        
    gpio_bit_reset(GPIOC, GPIO_PIN_7);
    vol_adc = Read_Adc_Data() & 0xFFFFFF;
    gpio_bit_set(GPIOC, GPIO_PIN_7);
}
nvic_irq_enable(EXTI5_9_IRQn, 1U, 0U);

}

/*中断开启需要先EA=1(总中断开)IT1=1;//下降沿触发

EX1=1;//开中断*/

/外部中断1响应函数 读取电流/
void EXTI4_IRQHandler(void)
{

if (RESET != exti_interrupt_flag_get(CURR_EXTI_LINE)) {
    nvic_irq_disable(EXTI4_IRQn);//关掉电流表中断 
    exti_interrupt_flag_clear(CURR_EXTI_LINE);
        
    gpio_bit_reset(GPIOA, GPIO_PIN_7);
    curr_adc = Read_Adc_Data() & 0xFFFFFF;
    gpio_bit_set(GPIOA, GPIO_PIN_7);
}
nvic_irq_enable(EXTI4_IRQn, 1U, 0U);

}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值