打印

基于GD32F303RC的多功能电表开发

[复制链接]
1747|14
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
一、硬件设计
(1)、主体方案
主控采用GD32F303,显示驱动采用HT16C23,电源为开关电源,采样转换芯片采用电量计量芯片RN8302,掉电保护采用内部flash和EEPROM,支持RS485通讯接口;
   
(2)、显示
显示采用笔段式液晶屏,驱动芯片采用HT16C23,与MCU采用IIC协议进行通讯,本次开发采用硬件IIC,不用模拟;
      
(3)、通讯
通讯采样RS485接口,位于电源板,采用modbus协议
(4)、采样

(5)、电源
电源采样开关电源,输出12V、5V、和3.3V

二、软件设计
(1)、HT16C23接口
//初始化背光控制并点亮屏幕
void back_light_config(void)
{
        rcu_periph_clock_enable(RCU_GPIOB);
       
        gpio_init(GPIOB,GPIO_MODE_OUT_PP,GPIO_OSPEED_MAX,GPIO_PIN_5);
       
        BG=1;
}


void HT16C23_interface_set(void)
{
        //使能时钟
        rcu_periph_clock_enable(RCU_GPIOB);
        rcu_periph_clock_enable(RCU_I2C1);
       
        //采用标准I2C协议
        gpio_init(GPIOB,GPIO_MODE_AF_OD,GPIO_OSPEED_MAX,GPIO_PIN_10);
        gpio_init(GPIOB,GPIO_MODE_AF_OD,GPIO_OSPEED_MAX,GPIO_PIN_11);
       
        //设置I2C1的时钟为400KHz
    i2c_clock_config(I2C1,400000,I2C_DTCY_2);
       
        //设置为I2C模式和GD32F303 的地址
    i2c_mode_addr_config(I2C1,I2C_I2CMODE_ENABLE,I2C_ADDFORMAT_7BITS,0x7c);//0x3e
   
        //使能I2C1和应答信号
        i2c_enable(I2C1);
    i2c_ack_config(I2C1,I2C_ACK_ENABLE);
}



void HT16C23_byte_write(u8 command, u8 command_set)
{
        //等待I2C1释放总线
    while(i2c_flag_get(I2C1, I2C_FLAG_I2CBSY));
       
        //GD32F303产生一个起始信号,等待起始信号发送完成       
    i2c_start_on_bus(I2C1);
    while(!i2c_flag_get(I2C1, I2C_FLAG_SBSEND));
       
        //发送从机写地址,等待发送完成,并清除标志
    i2c_master_addressing(I2C1, 0x7c, I2C_TRANSMITTER);//0x3e
    while(!i2c_flag_get(I2C1, I2C_FLAG_ADDSEND));
    i2c_flag_clear(I2C1,I2C_FLAG_ADDSEND);
       
        //等待发送缓冲区为空
    while(SET != i2c_flag_get(I2C1, I2C_FLAG_TBE));
       
        //发送命令,并等待发送完成
    i2c_data_transmit(I2C1, command);
    while(!i2c_flag_get(I2C1, I2C_FLAG_BTC));
       
        //发送命令设置,并等待发送完成
    i2c_data_transmit(I2C1, command_set);
    while(!i2c_flag_get(I2C1, I2C_FLAG_BTC));
       
        //GD32F303产生一个停止信号
    i2c_stop_on_bus(I2C1);
   
    while(I2C_CTL0(I2C1)&0x0200);
}
(2)显示相关函数

//相电压的显示界面
void show_phase_voltage(u32 ua,u32 ub,u32 uc,long long int tol)
{
        u8 vol_a_0=0,vol_a_1=0,vol_a_2=0,vol_a_3=0,vol_a_4=0;
        u8 vol_b_0=0,vol_b_1=0,vol_b_2=0,vol_b_3=0,vol_b_4=0;
        u8 vol_c_0=0,vol_c_1=0,vol_c_2=0,vol_c_3=0,vol_c_4=0;
        u8 tol_0=0,tol_1=0,tol_2=0,tol_3=0,tol_4=0,tol_5=0,tol_6=0,tol_7=0,tol_8=0;
        //显示‘U’和**
        Display_RAM_write_byte(0x80,seg_ram(12),0x49);
        LCD_wait_standby_state();
        Display_RAM_write_byte(0x80,seg_ram(13),0x89);
        LCD_wait_standby_state();
        //显示‘a’
        Display_RAM_write_byte(0x80,seg_ram(14),0x80);       
        LCD_wait_standby_state();
        //显示‘b’和‘c’
        Display_RAM_write_byte(0x80,seg_ram(16),0x22);
        LCD_wait_standby_state();
        //显示‘KV’、‘KWH’、‘TOTAL’
        if(ua>=1000000||ub>=1000000||uc>=1000000)
        {
                Display_RAM_write_byte(0x80,seg_ram(1),lcd_bit(1));
                LCD_wait_standby_state();
                Display_RAM_write_byte(0x80,seg_ram(43),lcd_bit(7));
                LCD_wait_standby_state();
                Display_RAM_write_byte(0x80,seg_ram(17),lcd_bit(7));
                LCD_wait_standby_state();
               
                vol_a_0=ua/10000/1000;
                vol_a_1=(ua-vol_a_0*10000*1000)/1000/1000;
                vol_a_2=(ua-vol_a_0*10000*1000-vol_a_1*1000*1000)/100/1000;
                vol_a_3=(ua-vol_a_0*10000*1000-vol_a_1*1000*1000-vol_a_2*100*1000)/10/1000;
                vol_a_4=(ua-vol_a_0*10000*1000-vol_a_1*1000*1000-vol_a_2*100*1000-vol_a_3*10*1000)/1000;
               
                vol_b_0=ub/10000/1000;
                vol_b_1=(ub-vol_b_0*10000*1000)/1000/1000;
                vol_b_2=(ub-vol_b_0*10000*1000-vol_b_1*1000*1000)/100/1000;
                vol_b_3=(ub-vol_b_0*10000*1000-vol_b_1*1000*1000-vol_b_2*100*1000)/10/1000;
                vol_b_4=(ub-vol_b_0*10000*1000-vol_b_1*1000*1000-vol_b_2*100*1000-vol_b_3*10*1000)/1000;
               
                vol_c_0=uc/10000/1000;
                vol_c_1=(uc-vol_c_0*10000*1000)/1000/1000;
                vol_c_2=(uc-vol_c_0*10000*1000-vol_c_1*1000*1000)/100/1000;
                vol_c_3=(uc-vol_c_0*10000*1000-vol_c_1*1000*1000-vol_c_2*100*1000)/10/1000;
                vol_c_4=(uc-vol_c_0*10000*1000-vol_c_1*1000*1000-vol_c_2*100*1000-vol_c_3*10*1000)/1000;
               
                tol_0=tol/100000000;
                tol_1=(tol-tol_0*100000000)/10000000;
                tol_2=(tol-tol_0*100000000-tol_1*10000000)/1000000;
                tol_3=(tol-tol_0*100000000-tol_1*10000000-tol_2*1000000)/100000;
                tol_4=(tol-tol_0*100000000-tol_1*10000000-tol_2*1000000-tol_3*100000)/10000;
                tol_5=(tol-tol_0*100000000-tol_1*10000000-tol_2*1000000-tol_3*100000-tol_4*10000)/1000;
                tol_6=(tol-tol_0*100000000-tol_1*10000000-tol_2*1000000-tol_3*100000-tol_4*10000-tol_5*1000)/100;
                tol_7=(tol-tol_0*100000000-tol_1*10000000-tol_2*1000000-tol_3*100000-tol_4*10000-tol_5*1000-tol_6*100)/10;
                tol_8=(tol-tol_0*100000000-tol_1*10000000-tol_2*1000000-tol_3*100000-tol_4*10000-tol_5*1000-tol_6*100-tol_7*10);
               
                //显示AB的电压
                Display_RAM_write_byte(0x80,seg_ram(11),num_ab_hig[vol_a_0]|(num_ab_hig[vol_b_0]>>4));
                Display_RAM_write_byte(0x80,seg_ram(10),num_ab_low[vol_a_0]|(num_ab_low[vol_b_0]>>4));
               
                Display_RAM_write_byte(0x80,seg_ram(9),num_ab_hig[vol_a_1]|(num_ab_hig[vol_b_1]>>4));
                Display_RAM_write_byte(0x80,seg_ram(8),num_ab_low[vol_a_1]|(num_ab_low[vol_b_1]>>4));
               
                Display_RAM_write_byte(0x80,seg_ram(7),num_ab_hig[vol_a_2]|(num_ab_hig[vol_b_2]>>4));
                Display_RAM_write_byte(0x80,seg_ram(6),num_ab_low[vol_a_2]|(num_ab_low[vol_b_2]>>4)|lcd_bit(4)|lcd_bit(0));
               
                Display_RAM_write_byte(0x80,seg_ram(5),num_ab_hig[vol_a_3]|(num_ab_hig[vol_b_3]>>4));
                Display_RAM_write_byte(0x80,seg_ram(4),num_ab_low[vol_a_3]|(num_ab_low[vol_b_3]>>4));
               
                Display_RAM_write_byte(0x80,seg_ram(3),num_ab_hig[vol_a_4]|(num_ab_hig[vol_b_4]>>4));
                Display_RAM_write_byte(0x80,seg_ram(2),num_ab_low[vol_a_4]|(num_ab_low[vol_b_4]>>4));
               
                //显示C相电压
                Display_RAM_write_byte(0x80,seg_ram(48),num_c[vol_c_0]);
                Display_RAM_write_byte(0x80,seg_ram(47),num_c[vol_c_1]);
                Display_RAM_write_byte(0x80,seg_ram(46),num_c[vol_c_2]|lcd_bit(7));
                Display_RAM_write_byte(0x80,seg_ram(45),num_c[vol_c_3]);
                Display_RAM_write_byte(0x80,seg_ram(44),num_c[vol_c_4]);
               
                //显示总电能
                Display_RAM_write_byte(0x80,seg_ram(18),num_tol[tol_0]);
                Display_RAM_write_byte(0x80,seg_ram(19),num_tol[tol_1]);
                Display_RAM_write_byte(0x80,seg_ram(20),num_tol[tol_2]);
                Display_RAM_write_byte(0x80,seg_ram(21),num_tol[tol_3]);
                Display_RAM_write_byte(0x80,seg_ram(22),num_tol[tol_4]);
                Display_RAM_write_byte(0x80,seg_ram(23),num_tol[tol_5]);
                Display_RAM_write_byte(0x80,seg_ram(24),num_tol[tol_6]|lcd_bit(0));
                Display_RAM_write_byte(0x80,seg_ram(25),num_tol[tol_7]);
                Display_RAM_write_byte(0x80,seg_ram(26),num_tol[tol_8]);
        }
        //显示‘V’、‘KWH’、‘TOTAL’
        else
        {
                Display_RAM_write_byte(0x80,seg_ram(1),lcd_bit(2));
                LCD_wait_standby_state();
                Display_RAM_write_byte(0x80,seg_ram(43),lcd_bit(7));
                LCD_wait_standby_state();
                Display_RAM_write_byte(0x80,seg_ram(17),lcd_bit(7));
                LCD_wait_standby_state();
               
                vol_a_0=ua/10000;
                vol_a_1=(ua-vol_a_0*10000)/1000;
                vol_a_2=(ua-vol_a_0*10000-vol_a_1*1000)/100;
                vol_a_3=(ua-vol_a_0*10000-vol_a_1*1000-vol_a_2*100)/10;
                vol_a_4=(ua-vol_a_0*10000-vol_a_1*1000-vol_a_2*100-vol_a_3*10);
               
                vol_b_0=ub/10000;
                vol_b_1=(ub-vol_b_0*10000)/1000;
                vol_b_2=(ub-vol_b_0*10000-vol_b_1*1000)/100;
                vol_b_3=(ub-vol_b_0*10000-vol_b_1*1000-vol_b_2*100)/10;
                vol_b_4=(ub-vol_b_0*10000-vol_b_1*1000-vol_b_2*100-vol_b_3*10);
               
                vol_c_0=uc/10000;
                vol_c_1=(uc-vol_c_0*10000)/1000;
                vol_c_2=(uc-vol_c_0*10000-vol_c_1*1000)/100;
                vol_c_3=(uc-vol_c_0*10000-vol_c_1*1000-vol_c_2*100)/10;
                vol_c_4=(uc-vol_c_0*10000-vol_c_1*1000-vol_c_2*100-vol_c_3*10);
               
                tol_0=tol/100000000;
                tol_1=(tol-tol_0*100000000)/10000000;
                tol_2=(tol-tol_0*100000000-tol_1*10000000)/1000000;
                tol_3=(tol-tol_0*100000000-tol_1*10000000-tol_2*1000000)/100000;
                tol_4=(tol-tol_0*100000000-tol_1*10000000-tol_2*1000000-tol_3*100000)/10000;
                tol_5=(tol-tol_0*100000000-tol_1*10000000-tol_2*1000000-tol_3*100000-tol_4*10000)/1000;
                tol_6=(tol-tol_0*100000000-tol_1*10000000-tol_2*1000000-tol_3*100000-tol_4*10000-tol_5*1000)/100;
                tol_7=(tol-tol_0*100000000-tol_1*10000000-tol_2*1000000-tol_3*100000-tol_4*10000-tol_5*1000-tol_6*100)/10;
                tol_8=(tol-tol_0*100000000-tol_1*10000000-tol_2*1000000-tol_3*100000-tol_4*10000-tol_5*1000-tol_6*100-tol_7*10);
               
                //显示AB的电压
                Display_RAM_write_byte(0x80,seg_ram(11),num_ab_hig[vol_a_0]|(num_ab_hig[vol_b_0]>>4));
                Display_RAM_write_byte(0x80,seg_ram(10),num_ab_low[vol_a_0]|(num_ab_low[vol_b_0]>>4));
               
                Display_RAM_write_byte(0x80,seg_ram(9),num_ab_hig[vol_a_1]|(num_ab_hig[vol_b_1]>>4));
                Display_RAM_write_byte(0x80,seg_ram(8),num_ab_low[vol_a_1]|(num_ab_low[vol_b_1]>>4));
               
                Display_RAM_write_byte(0x80,seg_ram(7),num_ab_hig[vol_a_2]|(num_ab_hig[vol_b_2]>>4));
                Display_RAM_write_byte(0x80,seg_ram(6),num_ab_low[vol_a_2]|(num_ab_low[vol_b_2]>>4)|lcd_bit(4)|lcd_bit(0));
               
                Display_RAM_write_byte(0x80,seg_ram(5),num_ab_hig[vol_a_3]|(num_ab_hig[vol_b_3]>>4));
                Display_RAM_write_byte(0x80,seg_ram(4),num_ab_low[vol_a_3]|(num_ab_low[vol_b_3]>>4));
               
                Display_RAM_write_byte(0x80,seg_ram(3),num_ab_hig[vol_a_4]|(num_ab_hig[vol_b_4]>>4));
                Display_RAM_write_byte(0x80,seg_ram(2),num_ab_low[vol_a_4]|(num_ab_low[vol_b_4]>>4));
               
                //显示C相电压
                Display_RAM_write_byte(0x80,seg_ram(48),num_c[vol_c_0]);
                Display_RAM_write_byte(0x80,seg_ram(47),num_c[vol_c_1]);
                Display_RAM_write_byte(0x80,seg_ram(46),num_c[vol_c_2]|lcd_bit(7));
                Display_RAM_write_byte(0x80,seg_ram(45),num_c[vol_c_3]);
                Display_RAM_write_byte(0x80,seg_ram(44),num_c[vol_c_4]);
               
                //显示总电能
                Display_RAM_write_byte(0x80,seg_ram(18),num_tol[tol_0]);
                Display_RAM_write_byte(0x80,seg_ram(19),num_tol[tol_1]);
                Display_RAM_write_byte(0x80,seg_ram(20),num_tol[tol_2]);
                Display_RAM_write_byte(0x80,seg_ram(21),num_tol[tol_3]);
                Display_RAM_write_byte(0x80,seg_ram(22),num_tol[tol_4]);
                Display_RAM_write_byte(0x80,seg_ram(23),num_tol[tol_5]);
                Display_RAM_write_byte(0x80,seg_ram(24),num_tol[tol_6]|lcd_bit(0));
                Display_RAM_write_byte(0x80,seg_ram(25),num_tol[tol_7]);
                Display_RAM_write_byte(0x80,seg_ram(26),num_tol[tol_8]);
        }
       
}
(3)RN8302接口
//写寄存器
u32 RN8302_reg_write(u8* pDataBuf, u8 nNum, u8 nAddr)
{
        u8 i,temp;
       
        RN8302_CS=0;       

        temp = nAddr|0x80;
        RN8302_send_byte(temp);
       
        for(i=0;i<nNum;i++)
        {
                RN8302_send_byte(pDataBuf[i]);
        }
       
        RN8302_CS=1;
        return 0;
}


//读寄存器
u32 RN8302_reg_read(u8 nNum, u8 nAddr,u8 Dummy_Byte)
{
        u32 Temp = 0;
        u8 Temp0 = 0, Temp1 = 0, Temp2 = 0, Temp3 = 0;

        RN8302_CS=0;
        RN8302_send_byte(nAddr);
       
        switch(nNum)
        {
                case 1:
                        Temp0 = RN8302_send_byte(Dummy_Byte);
                        Temp = Temp0;
                        break;
                case 2:
                        Temp0 = RN8302_send_byte(Dummy_Byte);
                        Temp1 = RN8302_send_byte(Dummy_Byte);
                        Temp = (Temp0 << 8) | Temp1;
                        break;
                case 3:
                        Temp0 = RN8302_send_byte(Dummy_Byte);
                        Temp1 = RN8302_send_byte(Dummy_Byte);
                        Temp2 = RN8302_send_byte(Dummy_Byte);
                        Temp = (Temp0 << 16) | (Temp1 << 8) | Temp2;
                        break;
                case 4:
                        Temp0 = RN8302_send_byte(Dummy_Byte);
                        Temp1 = RN8302_send_byte(Dummy_Byte);
                        Temp2 = RN8302_send_byte(Dummy_Byte);
                        Temp3 = RN8302_send_byte(Dummy_Byte);
                        Temp = (Temp0 << 24) | (Temp1 << 16) | (Temp2 << 8) | Temp3;
                        break;
                default:
                        break;
        }       
        RN8302_CS=1;
        return Temp;
}


三、总结
整体功能还在调试中,基本通讯和相关参数显示均已完成,

使用特权

评论回复
沙发
詹求实| | 2020-5-28 10:45 | 只看该作者
就是板子有点丑,需要加强改善,计算没有更好的算法吗?

使用特权

评论回复
板凳
guanjiaer| | 2020-6-3 15:30 | 只看该作者
非常感谢楼主分享

使用特权

评论回复
地板
磨砂| | 2020-6-3 15:31 | 只看该作者
板子很漂亮啊

使用特权

评论回复
5
晓伍| | 2020-6-3 15:31 | 只看该作者
代码好详细

使用特权

评论回复
6
八层楼| | 2020-6-3 15:31 | 只看该作者
楼主辛苦了

使用特权

评论回复
7
adee4210| | 2020-6-29 10:11 | 只看该作者
谢谢楼主分享,请问你的开关电源用的是什么电源芯片?

使用特权

评论回复
8
adee4210| | 2020-6-29 10:12 | 只看该作者
开关电源电路能分享一下吗?

使用特权

评论回复
9
steelen| | 2020-6-30 10:53 | 只看该作者
呵呵
板子好丑

使用特权

评论回复
10
Liyj336| | 2020-9-14 09:13 | 只看该作者
感谢楼主分享

使用特权

评论回复
11
lidi911| | 2020-9-16 20:49 | 只看该作者
这个分享不错

使用特权

评论回复
12
guijial511| | 2020-9-17 18:06 | 只看该作者
楼主这是要准备替换自己家的电表哇

使用特权

评论回复
13
明天真的好| | 2020-9-17 19:17 | 只看该作者
电源为开关电源,采样转换芯片采用电量计量芯片RN8302,掉电保护采用内部flash和EEPROM,支持RS485通讯接口;

使用特权

评论回复
14
名字是啥样| | 2020-9-18 09:14 | 只看该作者
板子做的很丑,不过能够实现功能就好了。加油吧。

使用特权

评论回复
15
fcccc| | 2020-9-18 14:18 | 只看该作者
不错的设计.

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

66

主题

1948

帖子

14

粉丝