6☞基于STM32的电子秤设计√★

Posted 行走的皮卡丘

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了6☞基于STM32的电子秤设计√★相关的知识,希望对你有一定的参考价值。

6、💗💗☞基于STM32的电子秤设计√★💗💗

Introduction

In the development of modern society, weighing technology has put forward higher requirements. At present, the use of desktop electronic scales in commercial trade has been quite common, but there are major limitations: large size, high cost, need for power frequency AC power supply, inconvenience to carry, and restricted applications. The existing portable scales are steelyards or spring scales that realize measurement by spring compression and tension deformation. Resident users use steelyards that have been explicitly eliminated by the state. For many years, people have been expecting that smart electronic scales with accurate measurement, convenient carrying, and low price will be put on the market.

This article designs a kind of intelligent electronic scale, discusses the working principle of the instrument, introduces the error of the instrument comes from the error distribution, and gives the circuit design and software flow of the instrument. The intelligent electronic scale is small in size, accurate in measurement, convenient to carry, simple in operation, fast in weighing, and integrates the function of mass weighing and price calculation. It can meet the needs of commercial trade and residential households and has broad application prospects.

引言

在现代社会的发展,对称重技术提出了更高的要求。目前,台式电子秤在商业贸易中的使用已相当普遍,但存在较大的局限性:体积大、成本高、需要工频交流电源供应、携带不便、应用场所受到制约。现有的便携秤为杆秤或弹簧压缩、拉伸变形来实现计量的弹簧秤,居民用户使用的是国家已经明令淘汰的杆秤。多年来,人们一直期待测量准确、携带方便、价格低廉的智能电子秤投放市场。

本文设计了一种智能电子秤,论述了仪器的工作原理,介绍了仪器的误差来源于误差分配,给出了仪器电路设计与软件流程。智能电子秤体积小、计量准确、携带方便、操作简单、称量速度快,并集质量称量功能与价格计算功能于一体,能够满足商业贸易和居民家庭的使用需求,具有广阔的应用前景。

1、系统概述

1.1、设计任务

用STM32设计一个电子秤。

1.2、设计要求

  • (1)称量范围0~10kg;分度值为0.001kg。仪器主要功能有自检、去皮、计价、单价设定、

  • (2)能够通过按键设置单价计算出总价等;

  • (3)设置的参数能够通过按键清零;

  • (4)具有LED显示接口。

  • (5)过载报警系统

2、 方案设计与论证

2.1、芯片选择方案

stm32是一个低功耗,高性能32位单片机,片内含4k Bytes ISP(In-system programmable)的可反复擦写1000次的Flash只读程序存储器。主要性能有:与MCS-51单片机产品兼容、全静态操作:0Hz~33Hz、 三级加密程序存储器、32个可编程I/O口线、三个16位定时器/计数器、八个中断源、全双工UART串行通道、掉电后中断可唤醒、看门狗定时器、双数据指针、掉电标识符、易编程。

2.2、 系统概述

本设计是一个具有计算功能的电子秤。由LCD1602液晶显示屏、HX711压力传感器芯片、声光电路驱动模块和按钮控制模块等组成,本项目研究一种用单片机控制的高精度智能电子秤设计方案。这种高精度智能电子秤体积小、计量准确、携带方便,集质量称量功能与价格计算功能于一体,能够满足商业贸易和居民家庭的使用需求。

2.3、设计要求

  • ①利用stm32组成一个电子秤。称量范围0~10kg;分度值为0.001kg。

  • ②仪器主要功能有自检、去皮、计价、单价设定、过载报警等。

  • ③通过LED可以正常显示

2.4、系统总体设计思路

本设计采用STM32F103C8T6 作为主控芯片,通过LCD液晶屏幕显示数据,以触控方式操作电子秤,采用电阻应变片桥式连接的称重传感器采集重量,以24位的HX711作为A/D转换芯片。最终可以实现称重,计价等功能。

2.5、各功能模块程序实现原理分析

该模块由全桥电阻应变式传感器模块,声光电路驱动模块,LCD1602模块和按钮控制模块组成。且都通过STM32来实现。

2.5.1、 全桥电阻应变式传感器

将应变片粘贴到受力的力敏型弹性元件上, 当弹性元件受力产生变形时,应变片产生相应的应变, 转化成电阻变化。将应变片接成如 图 3 所示的电桥,力引起的电阻变化将转换为测量电路的电压变化, 通过测量输出电压的数值, 再通过换算即可得到所测量物体的重量。

2.5.2 、LCD1602模块

点阵图形式液晶由M×N个显示单元组成,假设LCD显示屏有64行,每行有128列,每8列对应1字节的8位,即每行由16字节,共16×8=128个点组成,屏上64×16个显示单元与显示RAM区1024字节相对应,每一字节的内容和显示屏上相应位置的亮暗对应。

2.5.3、声光电路驱动模块

采用压电式蜂鸣器,压电式蜂鸣器主要由多谐振荡器、压电蜂鸣片、阻抗匹配器及共鸣箱、外壳等组成。多谐振荡器由晶体管或集成电路构成,当接通电源后(1.5-15V直流工作电压),多谐振荡器起振,输出1.5~2.5kHZ的音频信号,阻抗匹配器推动压电蜂鸣片发声。

2.5.4、 矩阵按钮模块

为了方便使用,知道设备的工作状态,增加了声光提示电路部分,刚上电的时候系统会进行去皮,当去皮结束之后蜂鸣器会响一下,下面蜂鸣器只有在所测物品超过量程的时候会响,而指示灯则是在去皮的时候回进行闪烁,结束后常亮,开始测量物品的时候长灭。

2.5.5、 HX711芯片

芯片内提供的稳压电源可以直接向外部传感器和芯片内的A/D 转换器提供电源,系统板上无需另外的模拟电源。芯片内的时钟振荡器不需要任何外接器件。上电自动复位功能简化了开机的初始化过程。

3、 STM32性能介绍及硬件设计

3.1、STM32单片机性能介绍

STM32它拥有的资源包括:48KB SRAM、256KB FLASH、2 个基本定时器、4 个通用定时器、2个高级定时器、2个DMA 控制器(共 12 个通道)、3 个SPI、2个IIC、5个串口、1个USB、1个CAN、3个12位ADC、1个12位DAC、1个SDIO接口及51 个通用IO口,该芯片性价比极高。

各个引脚说明如下:

  • PA0 作用1,按键 KEY_UP 2,可以做待机唤醒脚(WKUP) 3,可以接 DS18B20 传感器接口(P2 设置)

  • PA1作用1,NRF24L01 接口 IRQ 信号 2,接 HS0038 红外接收头(P2 设置)

  • PA2 作用 作为W25Q64 的片选信号

  • PA3 作用 作为SD 卡接口的片选脚

  • PA4 作用 作为NRF24L01 接口的 CE 信号

  • PA5 作用 作为W25Q64、SD 卡和 NRF24L01 接口的 SCK 信号

  • PA6 作用 作为 W25Q64、SD 卡和 NRF24L01 接口的 MISO 信号

  • PA7 作用 作为 W25Q64、SD 卡和 NRF24L01 接口的 MOSI 信号

  • PA8 作用 作为 接 DS0 LED 灯(红色)

  • PA9 作用 作为串口 1 TX 脚,默认连接 CH340 的 RX(P4 设置)

  • PA10 作用 作为串口 1 RX 脚,默认连接 CH340 的 TX(P4 设置)

  • PA11 作用 作为接 USB D-引脚

  • PA12 作用 作为接 USB D+引脚

  • PA13作用 作为JTAG/SWD 仿真接口,没接任何外设

  • PA14 作用 作为JTAG/SWD 仿真接口,没接任何外设

  • PA15 作用 作为1,JTAG 仿真口(JTDI) 2,PS/2 接口的 CLK 信号 3,接按键 KEY1

3.2、电子打铃系统硬件设计

该程序所需要的原理图,声光电路图,电源电路图以及LCD外部接线图依次如下图所示

4、 系统程序

4.1、主程序设计如下

主要包括的有,按键处理部分,声光提示部分,采集电压部分以及进行显示部分,整体工作上,由HX711进行数据采集转化,然后将转化好的数据送给单片机,单片机接收到数据,根据所输入的数据进行数据处理,最终显示到液晶屏幕上。流程如下:

4.1.1 ①主程序流程设计图如下图:

4.1.2 ②矩阵键盘程序设计如下图

4.1.3 ③液晶显示流程

4.2 主程序内容

#include "main.h"
#include "stm32f1xx_hal.h"
/* USER CODE BEGIN Includes */
#include "TIME.h"
#include "DISPLAY.h"
#include "LCD1602.h"
#include "MEMORY.h"
#include "weight.h"
#include "KEY.h"
#include "hx711.h

/* Private variables ---------------------------------------------------------*/
TIM_HandleTypeDef htim4;

/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
uint8_t FlagTest;
/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_TIM4_Init(void);
int main(void)
{
    HAL_Init();
    SystemClock_Config();
    HX711_Init();
    MX_GPIO_Init();
    MX_TIM4_Init();
    HAL_TIM_Base_Start_IT(&htim4);   //启动定时器
    LCD1602_cls();
    LCD1602_write(0,0x80);						//指针设置
    LCD1602_writebyte((unsigned char *)" Welcome To Use ");	//  
    LCD1602_write(0,0xc0);						//指针设置
    LCD1602_writebyte((unsigned char *)"Wlectronic Scale");
    Get_Maopi();
    while (1)
    {
        if (FlagTest==1)
        {
            Get_Weight();
            FlagTest = 0;
        }	
        dis_play();
        key_scan();		
    }
}

void SystemClock_Config(void)
{

  RCC_OscInitTypeDef RCC_OscInitStruct;
  RCC_ClkInitTypeDef RCC_ClkInitStruct;
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = 16;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI_DIV2;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL16;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }
  HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

    /**Configure the Systick 
    */
  HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

  /* SysTick_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}

/* TIM4 init function */
static void MX_TIM4_Init(void)
{

  TIM_ClockConfigTypeDef sClockSourceConfig;
  TIM_MasterConfigTypeDef sMasterConfig;

  htim4.Instance = TIM4;
  htim4.Init.Prescaler = 63;
  htim4.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim4.Init.Period = 10000;
  htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim4) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim4, &sClockSourceConfig) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim4, &sMasterConfig) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }
	
}

/** Configure pins as 
        * Analog 
        * Input 
        * Output
        * EVENT_OUT
        * EXTI
*/
static void MX_GPIO_Init(void)
{

  GPIO_InitTypeDef GPIO_InitStruct;

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET);

  /*Configure GPIO pin : PC13 */
  GPIO_InitStruct.Pin = GPIO_PIN_13;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

  /*Configure GPIO pin : PB0 */
  GPIO_InitStruct.Pin = GPIO_PIN_0;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  /*Configure GPIO pins : PB1 PB10 PB11 PB12 
                           PB13 PB14 PB15 */
  GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12 
                          |GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  /*Configure GPIO pin : PA8 */
  GPIO_InitStruct.Pin = GPIO_PIN_8;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

}
void _Error_Handler(char *file, int line)
{
  while(1)
  {
  }
}

#ifdef  USE_FULL_ASSERT
void assert_failed(uint8_t* file, uint32_t line)
{ 
}
#endif /* USE_FULL_ASSERT */

4.3、液晶LCD的显示

#include "LCD1602.h"

void LCD1602_delay(unsigned long T)	//短延时,主要函数调节1602时序的
{
	while(T--);
}

void LCD1602_write(unsigned char order,unsigned char dat)
//封装好的写数据/命令函数,第一个位置填写 0/1 分别对应 命令/数据,第二个位置填写数据		  
{
    LCD1602_e_0;
	
    if(order==0)LCD1602_rs_0;
	  else        LCD1602_rs_1;

    if((dat&0x80)==0x80) LCD1602_DB7_1;
    else 			        LCD1602_DB7_0;

    if((dat&0x40)==0x40) LCD1602_DB6_1;
    else 			        LCD1602_DB6_0;
	
    if((dat&0x20)==0x20) LCD1602_DB5_1;
    else 				      LCD1602_DB5_0;
	
    if((dat&0x10)==0x10) LCD1602_DB4_1;
    else 			        LCD1602_DB4_0;
	
    if((dat&0x08)==0x08) LCD1602_DB3_1;
    else 			        LCD1602_DB3_0;

    if((dat&0x04)==0x04) LCD1602_DB2_1;
    else 			        LCD1602_DB2_0;

    if((dat&0x02)==0x02) LCD1602_DB1_1;
    else 			        LCD1602_DB1_0;
	
    if((dat&0x01)==0x01) LCD1602_DB0_1;
    else 			        LCD1602_DB0_0;
    
    LCD1602_e_1;
    LCD1602_delay(400); //如果时序有问题,直接修改这个数据
    LCD1602_e_0;																								     
}

void LCD1602_writebyte(unsigned char *prointer)	//写一串数据函数,直接填写要显示的字符串			   
{
    while(*prointer!='\\0')
    {
        LCD1602_write(1,*prointer);
        prointer++;
    }
}

void LCD1602_cls(void )	            //初始化液晶
{
    HAL_Delay(20);
    LCD1602_GPIO_Configuration();
    LCD1602_delay(1500);	
    LCD1602_write(0,0x01);   LCD1602_delay(8000);	
    LCD1602_write(0,0x38);   LCD1602_delay(8000);	    //显示模式  功能设置 8位、5*7点阵
    LCD1602_write(0,0x38);   LCD1602_delay(8000);	    //显示模式  功能设置 8位、5*7点阵
    LCD1602_write(0,0x0c);   LCD1602_delay(8000);	    //开显示,不显示光标,不闪烁
    LCD1602_write(0,0x06);	 LCD1602_delay(8000);	  	//地址指针自动加1 
    LCD1602_write(0,0xd0);   LCD1602_delay(8000);

}
void LCD1602_GPIO_Configuration(void)   //GPIO 初始化
{
  GPIO_InitTypeDef GPIO_InitStruct;
  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOC_CLK_ENABLE();
  /*Configure GPIO pins  */
  GPIO_InitStruct.Pin = LCD1602_DB0|LCD1602_DB1|LCD1602_DB2|LCD1602_DB3|LCD1602_DB4|LCD1602_DB5|LCD1602_DB6|LCD1602_DB7;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(LCD1602_IO_GPIO, &GPIO_InitStruct);

  /*Configure GPIO pins  */
  GPIO_InitStruct.Pin = LCD1602_EN;
  HAL_GPIO_Init(LCD1602_EN_GPIO, &GPIO_InitStruct);	
  
  GPIO_InitStruct.Pin = LCD1602_RS;
  HAL_GPIO_Init(LCD1602_RS_GPIO, &GPIO_InitStruct);	
}

4.4、定时器内容

extern void key_scan(void);
extern TIM_HandleTypeDef htim4;
uint32_t Tim6_ms;
extern uint8_t FlagTest;
extern uint8_t beep1;

unsigned char  beep2;

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)  //定时器时间是10ms加一
{
    if(htim==(&htim4))
    {
        Tim6_ms++;
        if(Tim6_ms%5==0)
        {
            if(Weight_Shiwu!=0) 
            {
                if(Weight_Shiwu>9000) 
                {
                    if( beep2 == 1 ) 
                    {
                        beep2=0; 
                        BEEP_0;
                    }
                    else 
                    {
                        beep2=1; 
                        BEEP_1;
                    }	
                }else BEEP_0;
            }
        }
        if(Tim6_ms%50==0)
        {
            FlagTest=1;
        }
    }
}

4.5、传感器代码

#include "hx711.h"

void HX711_Init(void)              //初始化AD芯片使用的I/O端口。
{
    GPIO_InitTypeDef GPIO_InitStruct;

    /* GPIO Ports Clock Enable */
    __HAL_RCC_GPIOB_CLK_ENABLE();

    GPIO_InitStruct.Pin = GPIO_PIN_8;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_9;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}

void delay(uint32_t T)
{
    while(T--);
}

unsigned long HX711_Read(void)  //读取AD芯片输出的数据。
{
    unsigned long val = 0;
    unsigned char i = 0;

    HX711_DAT_1;
    HX711_SCK_0;
    while(HX711_DAT_READ==1);
    delay(2);
    for(i=0;i<24;i++)
    {
        HX711_SCK_1;
        val=val<<1;
        delay(2); 
        HX711_SCK_0;
        if(HX711_DAT_READ==1)
            val++;
        delay(2);
    }
    HX711_SCK_1;
    val = val^0x800000;
    delay(2

以上是关于6☞基于STM32的电子秤设计√★的主要内容,如果未能解决你的问题,请参考以下文章

基于STM32单片机项目设计目录-加油吧√

基于STM32单片机项目设计目录-加油吧√

基于STM32居家加湿器控制仿真系统设计-电子设计资料

19基于STM32的电子打铃器

19基于STM32的电子打铃器

12基于STM32的电子密码器