版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
开始之前
昨天接触到一块新的传感器—HX711。把玩了一下,最后在网上随便找了个驱动改了下,做了个简易电子秤,这里分享一下。
上代码
-
我使用的是正点原子家的mini版,所以有需要的小伙伴自己改一下芯片管脚就好了。
-
看代码
-
hx711.h
#ifndef _HX711_H_ #define _HX711_H_ #include "sys.h" void Init_Hx711(void); //初始化 uint32_t Hx_Read(void); //读取值 int32_t Get_Weight(void); //取重量 void Get_Maopi(void); //去皮 void numtostr(int16_t num, uint8_t str[]); //数字-字符串转换 #endif
-
hx711.c
#include "delay.h" #include "hx711.h" int32_t HX711_Buffer = 0; //HX711读取的数据值 int32_t Weight_Maopi; //全局变量,初始读取的重量,即毛皮 int32_t Weight_Shiwu = 0; //实际物品重量 //uint8_t numto3str[4]; //三位小数转换成字符串存放数组 #define GapValue 430 //数值转换参数 #define HIGH 1 #define LOW 0 #define HX711_GROUP GPIOC /** * @brief 置位或者复位管脚 * @param GPIOx:GPIOA-G * @param pin:pin0-15 * @param value:0(LOW) or 1(HIGH) 0为复位1为置位 * @return none * @details 对指定管脚进行置位或者复位,digitalWrite(GPIOC, pin0, 1) 为置位PC0管脚 */ void digitalWrite(GPIO_TypeDef * GPIOx, uint16_t pin, uint16_t value) { if(value==HIGH)//set 1 { GPIO_SetBits(GPIOx,pin); } if(value==LOW)//reset 0 { GPIO_ResetBits(GPIOx,pin); } } /** * @brief 读取某个管脚数据 * @param GPIOx:GPIOA-G * @param pin:pin0-15 * @return 读取的数据位 * @details 读取指定管脚的数据位,digitalRead(GPIOC, pin0) */ int16_t digitalRead(GPIO_TypeDef * GPIOx,uint16_t pin) { return GPIO_ReadInputDataBit(GPIOx,pin); } /** * @brief 初始化HX711 * @param None * @return None * @details 初始化HX711的DT,SCK引脚DT<----->PC0 ,SCK<----->PC13 */ void Init_Hx711() { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); //DT <-----> PC0 //SCK <-----> PC13 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //DT设置为浮空输入 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_Init(GPIOC, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //设置输出 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOC, &GPIO_InitStructure); } /** * @brief HX711读数据 * @param None * @return HX711一次读取到的数据 * @details val为24位数据,程序循环读取24次DT引脚电平数据,通过移位操 * 作写入val,注意!返回的并不是实际重量,只是一个采样电平值 */ uint32_t Hx_Read(void) //增益128 { uint32_t val = 0; uint8_t i = 0; GPIO_SetBits(GPIOC, GPIO_Pin_0); //初始状态DT引脚为高电平 GPIO_ResetBits(GPIOC, GPIO_Pin_13); //初始状态SCK引脚为低电平 //判断模块是否准备好 while(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_0)); delay_us(1); //sck 拉低 //GPIO_ResetBits(GPIOB,GPIO_Pin_6); //再次判断是否准备好 while(!GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_0)); for(i=0; i<24; i++) { delay_us(100); GPIO_SetBits(GPIOC,GPIO_Pin_13); val=val<<1; delay_us(1); GPIO_ResetBits(GPIOC,GPIO_Pin_13); if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_0)) val++; delay_us(1); } GPIO_SetBits(GPIOC,GPIO_Pin_13); val = val^0x800000; delay_us(1); GPIO_ResetBits(GPIOC,GPIO_Pin_13); delay_us(1); return val; } /** * @brief 获取毛皮重量 * @param None * @return None * @details 调用一次Hx_Read(),获取毛皮重量,并将采样值赋值给全局变量Weight_Maopi * @see Hx_Read(); */ void Get_Maopi() { Weight_Maopi = Hx_Read(); } /** * @brief 获取实物重量 * @param None * @return Weight_Shiwu:实物重量转换值 * @details 通过再一次获取重量,减去毛皮重量,剩下的就是实物重量,再通过传感器的约定取参, * 即可得到实物的实际重量。 * @see a reference to another function */ int32_t Get_Weight() { HX711_Buffer = Hx_Read(); Weight_Shiwu = HX711_Buffer; Weight_Shiwu = Weight_Shiwu - Weight_Maopi; //获取实物的AD采样数值。 Weight_Shiwu = (int32_t)((float)Weight_Shiwu/GapValue); return Weight_Shiwu; } /** * @brief 简单的三位数字转字符串 * @param num:要转换的参数 * @return None * @details 我们需要将x转换成00x,xx转换成0xx,xxx转换成xxx,库函数没有 * 对应功能,所以需要自己实现 */ void numtostr(int16_t num, uint8_t str[]) { int8_t i=2; while(i >= 0) { if(num != 0) { str[i] = (uint8_t)('0'+num%10); num /=10; } else { str[i] = (uint8_t)'0'; } --i; } str[3] = '\0'; }
-
main.c
#include "led.h" #include "delay.h" #include "sys.h" #include "usart.h" #include "key.h" #include "lcd.h" #include "string.h" #include "hx711.h" #include "includes.h" //START 任务 //设置任务优先级 #define START_TASK_PRIO 10 ///开始任务的优先级为最低 //设置任务堆栈大小 #define START_STK_SIZE 128 //任务任务堆栈 OS_STK START_TASK_STK[START_STK_SIZE]; //任务函数 void start_task(void *pdata); //LED1任务 防止程序跑飞 //设置任务优先级 #define LED1_TASK_PRIO 6 //设置任务堆栈大小 #define LED1_STK_SIZE 64 //任务堆栈 OS_STK LED1_TASK_STK[LED1_STK_SIZE]; //任务函数 void led1_task(void *pdata); //去皮称重任务 #define GETWEIGHT_TASK_PRIO 8 //设置任务堆栈大小 #define GETWEIGHT_STK_SIZE 128 //任务堆栈 OS_STK GETWEIGHT_TASK_STK[GETWEIGHT_STK_SIZE]; //任务函数 void getweight_task(void *pdata); int main(void) { delay_init(); //延时初始化 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断分组配置 uart_init(115200); //串口波特率设置 LED_Init(); //LED初始化 KEY_Init(); //按键初始化 LCD_Init(); //LCD初始化 Init_Hx711(); //HX711初始化 POINT_COLOR=RED;//设置字体为红色 LCD_ShowString(30,50,200,16,16,(u8 *)"Simple Electronic Scales"); //显示提示信息 POINT_COLOR=BLUE;//设置字体为蓝色 //显示提示 LCD_ShowString(30,110,200,16,16,(u8 *)"NOTE:"); LCD_ShowString(30,130,200,16,16,(u8 *)"Press Key1 to Peeled"); LCD_ShowString(30,150,200,16,16,(u8 *)"Press Key0 to get weight"); LCD_ShowString(30,170,200,16,16,(u8 *)"Press WK_UP to Zeroing"); LCD_ShowString(30,250,200,16,16,(u8 *)"Items's weight: kg"); OSInit(); //UCOS初始化 OSTaskCreate(start_task,(void*)0,(OS_STK*)&START_TASK_STK[START_STK_SIZE-1],START_TASK_PRIO); //创建开始任务 OSStart(); //开始任务 } //开始任务 void start_task(void *pdata) { OS_CPU_SR cpu_sr=0; pdata=pdata; OSStatInit(); //开启统计任务 OS_ENTER_CRITICAL(); //进入临界区(关闭中断) //创建LED1任务 OSTaskCreate(led1_task,(void*)0,(OS_STK*)&LED1_TASK_STK[LED1_STK_SIZE-1],LED1_TASK_PRIO); //创建称重任务 OSTaskCreate(getweight_task,(void*)0,(OS_STK*)&GETWEIGHT_TASK_STK[GETWEIGHT_STK_SIZE-1],GETWEIGHT_TASK_PRIO); OSTaskSuspend(START_TASK_PRIO);//挂起开始任务 OS_EXIT_CRITICAL(); //退出临界区(开中断) } //LED1任务,防止系统跑飞 void led1_task(void *pdata) { while(1) { LED1=0; delay_ms(300); LED1=1; delay_ms(300); } } void getweight_task(void *pdata) { int8_t keyval; //扫描按键值 float Weight = 0; //HX711读取的重量 INT16U iweight = 0; //重量整数部分 INT16U fweight = 0; //重量小数部分 uint8_t numto3str[4] = {0}; //小数部分抓换存放数组 while(1) { keyval = KEY_Scan(0); //案件扫描 if(keyval == WKUP_PRES) { keyval = -1; //LCD清零 LCD_ShowNum(150,250,00,2,16); LCD_ShowString(168,250,200,16,16,(u8 *)"."); LCD_ShowString(176,250,200,16,16,(u8 *)"000"); } if(keyval == KEY1_PRES) { keyval = -1; POINT_COLOR=RED;//设置字体为红色 OSTimeDlyHMSM (0,0,1,0); Get_Maopi(); //printf("ok\n"); //调试用 LCD_ShowString(30,200,200,16,16,(u8 *)"Peeled successfully"); LCD_ShowString(30,220,200,16,16,(u8 *)"start your weighing"); OSTimeDlyHMSM (0,0,2,0); //第一个参数是左边X坐标,第二个参数是上边Y坐标 //第三个参数是右边X坐标,第四个参数是下边Y坐标 LCD_Fill(30,200,2000,230,WHITE); OSTimeDlyHMSM (0,0,0,100); } if(keyval == KEY0_PRES) { keyval = -1; Weight = Get_Weight(); Weight = (float)Weight/1000.0f; iweight = (INT16U)Weight; fweight = (Weight-iweight)*1000; //iweight = 22; //调试用 //fweight = 40; //调试用 numtostr(fweight, numto3str); //把数字转换成带0字符串 //显示重量 LCD_ShowNum(150,250,iweight,2,16); LCD_ShowString(168,250,200,16,16,(u8 *)"."); LCD_ShowString(176,250,200,16,16,(u8 *)numto3str); //调试用 //printf("%0.3fkg %dkg %skg\n",Weight, fweight, (u8 *)numto3str); //变量清零 Weight = 0; iweight = 0; fweight = 0; OSTimeDlyHMSM (0,0,1,0); } } }
效果图
- 启动界面
- 去皮界面
- 称重界面
- 清零界面
工程文件
- 下载地址 云盘链接
- 提取码 p6v2