基于GD32F303RC的多功能电表开发

[复制链接]
2652|14
 楼主| zeshoufx 发表于 2020-5-27 19:46 | 显示全部楼层 |阅读模式
一、硬件设计
(1)、主体方案
主控采用GD32F303,显示驱动采用HT16C23,电源为开关电源,采样转换芯片采用电量计量芯片RN8302,掉电保护采用内部flash和EEPROM,支持RS485通讯接口;
952195ece516c40ff2.png     139075ece528b0d660.png
(2)、显示
显示采用笔段式液晶屏,驱动芯片采用HT16C23,与MCU采用IIC协议进行通讯,本次开发采用硬件IIC,不用模拟;
524325ece4f06ea34a.png        432965ece4f3b4229f.png
(3)、通讯
通讯采样RS485接口,位于电源板,采用modbus协议
(4)、采样
10635ece51844f997.png
(5)、电源
电源采样开关电源,输出12V、5V、和3.3V
731335ece50185d8c0.png
二、软件设计
(1)、HT16C23接口
  1. //初始化背光控制并点亮屏幕
  2. void back_light_config(void)
  3. {
  4.         rcu_periph_clock_enable(RCU_GPIOB);
  5.        
  6.         gpio_init(GPIOB,GPIO_MODE_OUT_PP,GPIO_OSPEED_MAX,GPIO_PIN_5);
  7.        
  8.         BG=1;
  9. }


  10. void HT16C23_interface_set(void)
  11. {
  12.         //使能时钟
  13.         rcu_periph_clock_enable(RCU_GPIOB);
  14.         rcu_periph_clock_enable(RCU_I2C1);
  15.        
  16.         //采用标准I2C协议
  17.         gpio_init(GPIOB,GPIO_MODE_AF_OD,GPIO_OSPEED_MAX,GPIO_PIN_10);
  18.         gpio_init(GPIOB,GPIO_MODE_AF_OD,GPIO_OSPEED_MAX,GPIO_PIN_11);
  19.        
  20.         //设置I2C1的时钟为400KHz
  21.     i2c_clock_config(I2C1,400000,I2C_DTCY_2);
  22.        
  23.         //设置为I2C模式和GD32F303 的地址
  24.     i2c_mode_addr_config(I2C1,I2C_I2CMODE_ENABLE,I2C_ADDFORMAT_7BITS,0x7c);//0x3e
  25.    
  26.         //使能I2C1和应答信号
  27.         i2c_enable(I2C1);
  28.     i2c_ack_config(I2C1,I2C_ACK_ENABLE);
  29. }



  30. void HT16C23_byte_write(u8 command, u8 command_set)
  31. {
  32.         //等待I2C1释放总线
  33.     while(i2c_flag_get(I2C1, I2C_FLAG_I2CBSY));
  34.        
  35.         //GD32F303产生一个起始信号,等待起始信号发送完成       
  36.     i2c_start_on_bus(I2C1);
  37.     while(!i2c_flag_get(I2C1, I2C_FLAG_SBSEND));
  38.        
  39.         //发送从机写地址,等待发送完成,并清除标志
  40.     i2c_master_addressing(I2C1, 0x7c, I2C_TRANSMITTER);//0x3e
  41.     while(!i2c_flag_get(I2C1, I2C_FLAG_ADDSEND));
  42.     i2c_flag_clear(I2C1,I2C_FLAG_ADDSEND);
  43.        
  44.         //等待发送缓冲区为空
  45.     while(SET != i2c_flag_get(I2C1, I2C_FLAG_TBE));
  46.        
  47.         //发送命令,并等待发送完成
  48.     i2c_data_transmit(I2C1, command);
  49.     while(!i2c_flag_get(I2C1, I2C_FLAG_BTC));
  50.        
  51.         //发送命令设置,并等待发送完成
  52.     i2c_data_transmit(I2C1, command_set);
  53.     while(!i2c_flag_get(I2C1, I2C_FLAG_BTC));
  54.        
  55.         //GD32F303产生一个停止信号
  56.     i2c_stop_on_bus(I2C1);
  57.    
  58.     while(I2C_CTL0(I2C1)&0x0200);
  59. }
(2)显示相关函数

  1. //相电压的显示界面
  2. void show_phase_voltage(u32 ua,u32 ub,u32 uc,long long int tol)
  3. {
  4.         u8 vol_a_0=0,vol_a_1=0,vol_a_2=0,vol_a_3=0,vol_a_4=0;
  5.         u8 vol_b_0=0,vol_b_1=0,vol_b_2=0,vol_b_3=0,vol_b_4=0;
  6.         u8 vol_c_0=0,vol_c_1=0,vol_c_2=0,vol_c_3=0,vol_c_4=0;
  7.         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;
  8.         //显示‘U’和**
  9.         Display_RAM_write_byte(0x80,seg_ram(12),0x49);
  10.         LCD_wait_standby_state();
  11.         Display_RAM_write_byte(0x80,seg_ram(13),0x89);
  12.         LCD_wait_standby_state();
  13.         //显示‘a’
  14.         Display_RAM_write_byte(0x80,seg_ram(14),0x80);       
  15.         LCD_wait_standby_state();
  16.         //显示‘b’和‘c’
  17.         Display_RAM_write_byte(0x80,seg_ram(16),0x22);
  18.         LCD_wait_standby_state();
  19.         //显示‘KV’、‘KWH’、‘TOTAL’
  20.         if(ua>=1000000||ub>=1000000||uc>=1000000)
  21.         {
  22.                 Display_RAM_write_byte(0x80,seg_ram(1),lcd_bit(1));
  23.                 LCD_wait_standby_state();
  24.                 Display_RAM_write_byte(0x80,seg_ram(43),lcd_bit(7));
  25.                 LCD_wait_standby_state();
  26.                 Display_RAM_write_byte(0x80,seg_ram(17),lcd_bit(7));
  27.                 LCD_wait_standby_state();
  28.                
  29.                 vol_a_0=ua/10000/1000;
  30.                 vol_a_1=(ua-vol_a_0*10000*1000)/1000/1000;
  31.                 vol_a_2=(ua-vol_a_0*10000*1000-vol_a_1*1000*1000)/100/1000;
  32.                 vol_a_3=(ua-vol_a_0*10000*1000-vol_a_1*1000*1000-vol_a_2*100*1000)/10/1000;
  33.                 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;
  34.                
  35.                 vol_b_0=ub/10000/1000;
  36.                 vol_b_1=(ub-vol_b_0*10000*1000)/1000/1000;
  37.                 vol_b_2=(ub-vol_b_0*10000*1000-vol_b_1*1000*1000)/100/1000;
  38.                 vol_b_3=(ub-vol_b_0*10000*1000-vol_b_1*1000*1000-vol_b_2*100*1000)/10/1000;
  39.                 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;
  40.                
  41.                 vol_c_0=uc/10000/1000;
  42.                 vol_c_1=(uc-vol_c_0*10000*1000)/1000/1000;
  43.                 vol_c_2=(uc-vol_c_0*10000*1000-vol_c_1*1000*1000)/100/1000;
  44.                 vol_c_3=(uc-vol_c_0*10000*1000-vol_c_1*1000*1000-vol_c_2*100*1000)/10/1000;
  45.                 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;
  46.                
  47.                 tol_0=tol/100000000;
  48.                 tol_1=(tol-tol_0*100000000)/10000000;
  49.                 tol_2=(tol-tol_0*100000000-tol_1*10000000)/1000000;
  50.                 tol_3=(tol-tol_0*100000000-tol_1*10000000-tol_2*1000000)/100000;
  51.                 tol_4=(tol-tol_0*100000000-tol_1*10000000-tol_2*1000000-tol_3*100000)/10000;
  52.                 tol_5=(tol-tol_0*100000000-tol_1*10000000-tol_2*1000000-tol_3*100000-tol_4*10000)/1000;
  53.                 tol_6=(tol-tol_0*100000000-tol_1*10000000-tol_2*1000000-tol_3*100000-tol_4*10000-tol_5*1000)/100;
  54.                 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;
  55.                 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);
  56.                
  57.                 //显示AB的电压
  58.                 Display_RAM_write_byte(0x80,seg_ram(11),num_ab_hig[vol_a_0]|(num_ab_hig[vol_b_0]>>4));
  59.                 Display_RAM_write_byte(0x80,seg_ram(10),num_ab_low[vol_a_0]|(num_ab_low[vol_b_0]>>4));
  60.                
  61.                 Display_RAM_write_byte(0x80,seg_ram(9),num_ab_hig[vol_a_1]|(num_ab_hig[vol_b_1]>>4));
  62.                 Display_RAM_write_byte(0x80,seg_ram(8),num_ab_low[vol_a_1]|(num_ab_low[vol_b_1]>>4));
  63.                
  64.                 Display_RAM_write_byte(0x80,seg_ram(7),num_ab_hig[vol_a_2]|(num_ab_hig[vol_b_2]>>4));
  65.                 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));
  66.                
  67.                 Display_RAM_write_byte(0x80,seg_ram(5),num_ab_hig[vol_a_3]|(num_ab_hig[vol_b_3]>>4));
  68.                 Display_RAM_write_byte(0x80,seg_ram(4),num_ab_low[vol_a_3]|(num_ab_low[vol_b_3]>>4));
  69.                
  70.                 Display_RAM_write_byte(0x80,seg_ram(3),num_ab_hig[vol_a_4]|(num_ab_hig[vol_b_4]>>4));
  71.                 Display_RAM_write_byte(0x80,seg_ram(2),num_ab_low[vol_a_4]|(num_ab_low[vol_b_4]>>4));
  72.                
  73.                 //显示C相电压
  74.                 Display_RAM_write_byte(0x80,seg_ram(48),num_c[vol_c_0]);
  75.                 Display_RAM_write_byte(0x80,seg_ram(47),num_c[vol_c_1]);
  76.                 Display_RAM_write_byte(0x80,seg_ram(46),num_c[vol_c_2]|lcd_bit(7));
  77.                 Display_RAM_write_byte(0x80,seg_ram(45),num_c[vol_c_3]);
  78.                 Display_RAM_write_byte(0x80,seg_ram(44),num_c[vol_c_4]);
  79.                
  80.                 //显示总电能
  81.                 Display_RAM_write_byte(0x80,seg_ram(18),num_tol[tol_0]);
  82.                 Display_RAM_write_byte(0x80,seg_ram(19),num_tol[tol_1]);
  83.                 Display_RAM_write_byte(0x80,seg_ram(20),num_tol[tol_2]);
  84.                 Display_RAM_write_byte(0x80,seg_ram(21),num_tol[tol_3]);
  85.                 Display_RAM_write_byte(0x80,seg_ram(22),num_tol[tol_4]);
  86.                 Display_RAM_write_byte(0x80,seg_ram(23),num_tol[tol_5]);
  87.                 Display_RAM_write_byte(0x80,seg_ram(24),num_tol[tol_6]|lcd_bit(0));
  88.                 Display_RAM_write_byte(0x80,seg_ram(25),num_tol[tol_7]);
  89.                 Display_RAM_write_byte(0x80,seg_ram(26),num_tol[tol_8]);
  90.         }
  91.         //显示‘V’、‘KWH’、‘TOTAL’
  92.         else
  93.         {
  94.                 Display_RAM_write_byte(0x80,seg_ram(1),lcd_bit(2));
  95.                 LCD_wait_standby_state();
  96.                 Display_RAM_write_byte(0x80,seg_ram(43),lcd_bit(7));
  97.                 LCD_wait_standby_state();
  98.                 Display_RAM_write_byte(0x80,seg_ram(17),lcd_bit(7));
  99.                 LCD_wait_standby_state();
  100.                
  101.                 vol_a_0=ua/10000;
  102.                 vol_a_1=(ua-vol_a_0*10000)/1000;
  103.                 vol_a_2=(ua-vol_a_0*10000-vol_a_1*1000)/100;
  104.                 vol_a_3=(ua-vol_a_0*10000-vol_a_1*1000-vol_a_2*100)/10;
  105.                 vol_a_4=(ua-vol_a_0*10000-vol_a_1*1000-vol_a_2*100-vol_a_3*10);
  106.                
  107.                 vol_b_0=ub/10000;
  108.                 vol_b_1=(ub-vol_b_0*10000)/1000;
  109.                 vol_b_2=(ub-vol_b_0*10000-vol_b_1*1000)/100;
  110.                 vol_b_3=(ub-vol_b_0*10000-vol_b_1*1000-vol_b_2*100)/10;
  111.                 vol_b_4=(ub-vol_b_0*10000-vol_b_1*1000-vol_b_2*100-vol_b_3*10);
  112.                
  113.                 vol_c_0=uc/10000;
  114.                 vol_c_1=(uc-vol_c_0*10000)/1000;
  115.                 vol_c_2=(uc-vol_c_0*10000-vol_c_1*1000)/100;
  116.                 vol_c_3=(uc-vol_c_0*10000-vol_c_1*1000-vol_c_2*100)/10;
  117.                 vol_c_4=(uc-vol_c_0*10000-vol_c_1*1000-vol_c_2*100-vol_c_3*10);
  118.                
  119.                 tol_0=tol/100000000;
  120.                 tol_1=(tol-tol_0*100000000)/10000000;
  121.                 tol_2=(tol-tol_0*100000000-tol_1*10000000)/1000000;
  122.                 tol_3=(tol-tol_0*100000000-tol_1*10000000-tol_2*1000000)/100000;
  123.                 tol_4=(tol-tol_0*100000000-tol_1*10000000-tol_2*1000000-tol_3*100000)/10000;
  124.                 tol_5=(tol-tol_0*100000000-tol_1*10000000-tol_2*1000000-tol_3*100000-tol_4*10000)/1000;
  125.                 tol_6=(tol-tol_0*100000000-tol_1*10000000-tol_2*1000000-tol_3*100000-tol_4*10000-tol_5*1000)/100;
  126.                 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;
  127.                 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);
  128.                
  129.                 //显示AB的电压
  130.                 Display_RAM_write_byte(0x80,seg_ram(11),num_ab_hig[vol_a_0]|(num_ab_hig[vol_b_0]>>4));
  131.                 Display_RAM_write_byte(0x80,seg_ram(10),num_ab_low[vol_a_0]|(num_ab_low[vol_b_0]>>4));
  132.                
  133.                 Display_RAM_write_byte(0x80,seg_ram(9),num_ab_hig[vol_a_1]|(num_ab_hig[vol_b_1]>>4));
  134.                 Display_RAM_write_byte(0x80,seg_ram(8),num_ab_low[vol_a_1]|(num_ab_low[vol_b_1]>>4));
  135.                
  136.                 Display_RAM_write_byte(0x80,seg_ram(7),num_ab_hig[vol_a_2]|(num_ab_hig[vol_b_2]>>4));
  137.                 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));
  138.                
  139.                 Display_RAM_write_byte(0x80,seg_ram(5),num_ab_hig[vol_a_3]|(num_ab_hig[vol_b_3]>>4));
  140.                 Display_RAM_write_byte(0x80,seg_ram(4),num_ab_low[vol_a_3]|(num_ab_low[vol_b_3]>>4));
  141.                
  142.                 Display_RAM_write_byte(0x80,seg_ram(3),num_ab_hig[vol_a_4]|(num_ab_hig[vol_b_4]>>4));
  143.                 Display_RAM_write_byte(0x80,seg_ram(2),num_ab_low[vol_a_4]|(num_ab_low[vol_b_4]>>4));
  144.                
  145.                 //显示C相电压
  146.                 Display_RAM_write_byte(0x80,seg_ram(48),num_c[vol_c_0]);
  147.                 Display_RAM_write_byte(0x80,seg_ram(47),num_c[vol_c_1]);
  148.                 Display_RAM_write_byte(0x80,seg_ram(46),num_c[vol_c_2]|lcd_bit(7));
  149.                 Display_RAM_write_byte(0x80,seg_ram(45),num_c[vol_c_3]);
  150.                 Display_RAM_write_byte(0x80,seg_ram(44),num_c[vol_c_4]);
  151.                
  152.                 //显示总电能
  153.                 Display_RAM_write_byte(0x80,seg_ram(18),num_tol[tol_0]);
  154.                 Display_RAM_write_byte(0x80,seg_ram(19),num_tol[tol_1]);
  155.                 Display_RAM_write_byte(0x80,seg_ram(20),num_tol[tol_2]);
  156.                 Display_RAM_write_byte(0x80,seg_ram(21),num_tol[tol_3]);
  157.                 Display_RAM_write_byte(0x80,seg_ram(22),num_tol[tol_4]);
  158.                 Display_RAM_write_byte(0x80,seg_ram(23),num_tol[tol_5]);
  159.                 Display_RAM_write_byte(0x80,seg_ram(24),num_tol[tol_6]|lcd_bit(0));
  160.                 Display_RAM_write_byte(0x80,seg_ram(25),num_tol[tol_7]);
  161.                 Display_RAM_write_byte(0x80,seg_ram(26),num_tol[tol_8]);
  162.         }
  163.        
  164. }
(3)RN8302接口
  1. //写寄存器
  2. u32 RN8302_reg_write(u8* pDataBuf, u8 nNum, u8 nAddr)
  3. {
  4.         u8 i,temp;
  5.        
  6.         RN8302_CS=0;       

  7.         temp = nAddr|0x80;
  8.         RN8302_send_byte(temp);
  9.        
  10.         for(i=0;i<nNum;i++)
  11.         {
  12.                 RN8302_send_byte(pDataBuf[i]);
  13.         }
  14.        
  15.         RN8302_CS=1;
  16.         return 0;
  17. }


  18. //读寄存器
  19. u32 RN8302_reg_read(u8 nNum, u8 nAddr,u8 Dummy_Byte)
  20. {
  21.         u32 Temp = 0;
  22.         u8 Temp0 = 0, Temp1 = 0, Temp2 = 0, Temp3 = 0;

  23.         RN8302_CS=0;
  24.         RN8302_send_byte(nAddr);
  25.        
  26.         switch(nNum)
  27.         {
  28.                 case 1:
  29.                         Temp0 = RN8302_send_byte(Dummy_Byte);
  30.                         Temp = Temp0;
  31.                         break;
  32.                 case 2:
  33.                         Temp0 = RN8302_send_byte(Dummy_Byte);
  34.                         Temp1 = RN8302_send_byte(Dummy_Byte);
  35.                         Temp = (Temp0 << 8) | Temp1;
  36.                         break;
  37.                 case 3:
  38.                         Temp0 = RN8302_send_byte(Dummy_Byte);
  39.                         Temp1 = RN8302_send_byte(Dummy_Byte);
  40.                         Temp2 = RN8302_send_byte(Dummy_Byte);
  41.                         Temp = (Temp0 << 16) | (Temp1 << 8) | Temp2;
  42.                         break;
  43.                 case 4:
  44.                         Temp0 = RN8302_send_byte(Dummy_Byte);
  45.                         Temp1 = RN8302_send_byte(Dummy_Byte);
  46.                         Temp2 = RN8302_send_byte(Dummy_Byte);
  47.                         Temp3 = RN8302_send_byte(Dummy_Byte);
  48.                         Temp = (Temp0 << 24) | (Temp1 << 16) | (Temp2 << 8) | Temp3;
  49.                         break;
  50.                 default:
  51.                         break;
  52.         }       
  53.         RN8302_CS=1;
  54.         return Temp;
  55. }


三、总结
整体功能还在调试中,基本通讯和相关参数显示均已完成,
詹求实 发表于 2020-5-28 10:45 | 显示全部楼层
就是板子有点丑,需要加强改善,计算没有更好的算法吗?
guanjiaer 发表于 2020-6-3 15:30 | 显示全部楼层
非常感谢楼主分享
磨砂 发表于 2020-6-3 15:31 | 显示全部楼层
板子很漂亮啊
晓伍 发表于 2020-6-3 15:31 | 显示全部楼层
代码好详细
八层楼 发表于 2020-6-3 15:31 | 显示全部楼层
楼主辛苦了
adee4210 发表于 2020-6-29 10:11 | 显示全部楼层
谢谢楼主分享,请问你的开关电源用的是什么电源芯片?
adee4210 发表于 2020-6-29 10:12 | 显示全部楼层
开关电源电路能分享一下吗?
steelen 发表于 2020-6-30 10:53 | 显示全部楼层
呵呵
板子好丑
Liyj336 发表于 2020-9-14 09:13 | 显示全部楼层
感谢楼主分享
lidi911 发表于 2020-9-16 20:49 | 显示全部楼层
这个分享不错
guijial511 发表于 2020-9-17 18:06 来自手机 | 显示全部楼层
楼主这是要准备替换自己家的电表哇
明天真的好 发表于 2020-9-17 19:17 | 显示全部楼层
电源为开关电源,采样转换芯片采用电量计量芯片RN8302,掉电保护采用内部flash和EEPROM,支持RS485通讯接口;
名字是啥样 发表于 2020-9-18 09:14 | 显示全部楼层
板子做的很丑,不过能够实现功能就好了。加油吧。
fcccc 发表于 2020-9-18 14:18 | 显示全部楼层
不错的设计.
您需要登录后才可以回帖 登录 | 注册

本版积分规则

67

主题

1992

帖子

15

粉丝
快速回复 在线客服 返回列表 返回顶部