STM32F103 用CS1237 /HX711 芯片制作电子秤

【注:学习STM32总结做的笔记,大神勿喷。有不足之处还望不吝赐教,谢谢。工程代码在最后。】

19年全国大学生电子设计大赛 简易多功能液体容器电子秤 CS1237 HX711 压力传感器 STM32F103 2019年全国大学生电子设计竞赛试题清单 2019年全国大学生电子设计竞赛仪器设备和主要元器件清单


【福利/参考/学习资料】
2019年全国大学生电子设计竞赛仪器设备和主要元器件清单
2019年全国大学生电子设计竞赛试题清单
2017年全国大学生电子设计竞赛仪器设备和主要元器件清单
全国大学生电子设计竞赛资料(收集)
https://pan.baidu.com/s/1Ayy-kWOaLqlpOQgsYy7UUw
https://pan.baidu.com/s/1fhTiDL7GUUBYx-WcJoWHNQ
https://pan.baidu.com/s/1–VqCzF2nMporwkkKYIrXw
https://pan.baidu.com/s/1eIk9hmbHhbBSZ4tW1o1T7Q
(文件太多,只能分开)

本人有幸参与了19年的全国大学生电子设计大赛(广东赛区选拔赛),选择了K题,制作简易多功能液体容器,(即,电子秤与及检测重量、分辨不同液体和高度、密度等物理量)。

电子秤制作原理什么的就不多介绍了,下面链接是电子秤制作原理,想具体了解的,可以看看。
http://www.doc88.com/p-695275844769.html
这比赛呢,我们团队使用超声波测高、电子秤测重、PH计测酸、电导计测电导,从物理、化学的角度考虑,通过不同传感器检测不同液体AD值,从而区分不同液体,具体怎么做就不细说了。。


本篇就只简单介绍STM32F103 用CS1237 /HX711 芯片制作电子秤,比赛其他的就不涉及了。

直接上原理图:

测重,用 CS1237 和 HX711 芯片,其实做法一样,只要数据稳定,都能精准检测。程序写法都一样的,反正这两种芯片我都试了,都ok的,但下面我就以CS1237芯片的为例。
下面就看代码吧,我把要注意的都注释说明了,不懂再联系我。
就是为了数据的精准度,我采用了多次分段测量,求重量和AD的关系;然后通过每次测量得到的AD,反推,就能得到一个精准的重量。
注:压力传感器形变测量有最大限制,如果超过后可能会造成永久性物理损坏。

mian.c

#include "stm32f10x.h"
#include "uart.h"
#include "cs1237.h"
#include "key.h"/*2019.8.12 子非鱼测重,用 CS1237 和 HX711 芯片,其实做法一样,只要数据稳定,都能精准检测。程序写法都一样的。
*/float one_weight=0,two_weight,weight,zhun_weight,zhongliang;     //重量int main(void)
{   int i;  int32_t temp,adc,one_zhongliang; //  ,zhongliangUSART1_Init(); // 初始化串口1 波特率9600CS1237_Init_JX();delay_ms(300);CS1237_Config();delay_ms(100);USART1_Send_byte(Read_Config());/*第一次取值 用作基准值 用于复位后去皮用 我比赛时没用到这段*///   for(i=0;i<20;i++)  /* 用于复位后 循环取第19次值 前面的值用于稳定数据 */
//  {
//      weight = Read_CS1237();/*读取CS1237的数据*/
//      weight = weight + 28000; /* +28000 是因为传感器/芯片的原因导致读回来的值,是负值(-20500~正数++)。需要制零(尽可能接近零),方便从零开始计数。也有些是往负数++ ,这需要看情况。 */
//      if(i==19)
//      {
//      one_weight = weight;
//      }
//  //  printf("*******%f/r/n  ",one_weight);
//  }
//  delay_ms(100);while (1){
///
/*
实时按键去皮(清零)
跟上面注释的说明一样的,现在只是实时按键清零而已
*/if(KEY1==0){delay_ms(10);one_weight = Read_CS1237();//读取CS1237的数据one_weight = one_weight + 28000;                    }
/       two_weight = Read_CS1237();//读取CS1237的数据two_weight = two_weight + 28000;//取一次值,处理一次two_weight = two_weight - one_weight; /* one_weight定义时值要为零,否则会出错 */weight     = two_weight/100000; //这里对读取CS1237的数据 缩小了100000倍(可以缩小,也可以不缩小。我的缩小了)//      printf("*******%f/r/n  ",weight);//*
下面采用数据分段计算的方法,以求更高的精度c = ad / g  被测物质量g                  对应值ad ( weight )                系数c ( ad/g )
50                             0.210                            0.0042
100                            0.420                            0.0042
150                            0.629                            0.00419
200                            0.833                            0.004165
250                            1.044                            0.004176
300                            1.253                            0.004177
...                            ...                              ...
900                            3.766                            0.004184
*//*
转化为克g  = ad / c
zhongliang = weight / c判断读取CS1237的数据weight的值,落在哪个区间,然后选取相应的 系数c ( ad/g ) 值
*/if(weight>0.001&&weight<0.2101){zhongliang = weight / 0.0042  ;} //50gif(weight>0.210&&weight<0.4201){zhongliang = weight / 0.0042  ;} //100gif(weight>0.420&&weight<0.6291){zhongliang = weight / 0.00419 ;} //150g     if(weight>0.629&&weight<1.8331){zhongliang = weight / 0.004165 ;} //200gif(weight>0.833&&weight<1.0441){zhongliang = weight / 0.004176 ;} //250gif(weight>1.044&&weight<1.2531){zhongliang = weight / 0.004177 ;} //300gif(weight>1.253&&weight<1.4641){zhongliang = weight / 0.004183 ;} //350gif(weight>1.464&&weight<1.6661){zhongliang = weight / 0.004165 ;} //400gif(weight>1.666&&weight<1.8741){zhongliang = weight / 0.004164 ;} //450gif(weight>1.874&&weight<2.0851){zhongliang = weight / 0.00417 ;} //500gif(weight>2.085&&weight<2.2961){zhongliang = weight / 0.0041745 ;} //550gif(weight>2.296&&weight<2.5071){zhongliang = weight / 0.00418 ;} //600gif(weight>2.507&&weight<2.7171){zhongliang = weight / 0.00418 ;} //650gif(weight>2.717&&weight<2.9241){zhongliang = weight / 0.004178 ;} //700gif(weight>2.924&&weight<3.1381){zhongliang = weight / 0.004175 ;} //750gif(weight>3.138&&weight<3.3481){zhongliang = weight / 0.004185 ;} //800gif(weight>3.348&&weight<3.5561){zhongliang = weight / 0.0041835 ;} //850gif(weight>3.556&&weight<3.7661){zhongliang = weight / 0.0041844 ;} //900gif(weight>3.766)               {zhongliang = weight / 0.004191 ;} //900g以上printf("*******%f*********%f/r/n  ",weight,zhongliang);}   }

**

cs1237.c

**

#include "cs1237.h"
#include "uart.h"//OUT引脚输入输出 方向设置  PA3
#define OUT_IN()  {GPIOA->CRL&=0XFFFF0FFF;GPIOA->CRL|=8<<12;}
#define OUT_OUT() {GPIOA->CRL&=0XFFFF0FFF;GPIOA->CRL|=3<<12;}// PA2-----CLK
// PA3-----OUTvoid Delay1us(void)
{__IO uint32_t t=5;while(t--);
}void Delay1ms(void)
{__IO uint32_t t=8000;while(t--);
}void delay_ms(__IO uint16_t ms)
{do{Delay1ms();}while(ms--);
}// 初始化PA2 PA3
// PA2-----CLK
// PA3-----OUT
void CS1237_Init_JX(void)
{   GPIO_InitTypeDef  GPIO_InitStructure;                   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);   // PA2 ----- CLK  设置为输出// PA3 ----- OUT  设置为输出GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3;       GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;       GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;      GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_SetBits(GPIOA, GPIO_Pin_2);  // CLK拉高GPIO_SetBits(GPIOA, GPIO_Pin_3);    // OUT拉高
}//配置CS1237芯片
void CS1237_Config(void)
{unsigned char i;unsigned char dat;unsigned int count_i=0;//溢出计时器dat = 0X0C;   //芯片地配置 内部REF 输出40HZ PGA=128 通道A 0X1C   OUT_OUT();GPIO_SetBits(GPIOA, GPIO_Pin_3); //OUT引脚拉高OUT_IN();GPIO_ResetBits(GPIOA, GPIO_Pin_2);// 时钟拉低while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_3)==1) //等待CS237准备好{delay_ms(1);count_i++;if(count_i > 300){OUT_OUT();GPIO_SetBits(GPIOA, GPIO_Pin_3); // OUT引脚拉高GPIO_SetBits(GPIOA, GPIO_Pin_2); // CLK引脚拉高return;//超时,则直接退出程序}}for(i=0;i<29;i++)// 1 - 29{GPIO_SetBits(GPIOA, GPIO_Pin_2);    // CLK=1;Delay1us();GPIO_ResetBits(GPIOA, GPIO_Pin_2); // CLK=0;Delay1us();}OUT_OUT();GPIO_SetBits(GPIOA, GPIO_Pin_2);Delay1us();GPIO_SetBits(GPIOA, GPIO_Pin_3);GPIO_ResetBits(GPIOA, GPIO_Pin_2);Delay1us();//30GPIO_SetBits(GPIOA, GPIO_Pin_2);Delay1us();GPIO_SetBits(GPIOA, GPIO_Pin_3);GPIO_ResetBits(GPIOA, GPIO_Pin_2);Delay1us();//31GPIO_SetBits(GPIOA, GPIO_Pin_2);Delay1us();GPIO_ResetBits(GPIOA, GPIO_Pin_3);GPIO_ResetBits(GPIOA, GPIO_Pin_2);Delay1us();//32GPIO_SetBits(GPIOA, GPIO_Pin_2);Delay1us();GPIO_ResetBits(GPIOA, GPIO_Pin_3);GPIO_ResetBits(GPIOA, GPIO_Pin_2);Delay1us();//33GPIO_SetBits(GPIOA, GPIO_Pin_2);Delay1us();GPIO_SetBits(GPIOA, GPIO_Pin_3);GPIO_ResetBits(GPIOA, GPIO_Pin_2);Delay1us();//34GPIO_SetBits(GPIOA, GPIO_Pin_2);Delay1us();GPIO_ResetBits(GPIOA, GPIO_Pin_3);GPIO_ResetBits(GPIOA, GPIO_Pin_2);Delay1us();//35GPIO_SetBits(GPIOA, GPIO_Pin_2);Delay1us();GPIO_SetBits(GPIOA, GPIO_Pin_3);GPIO_ResetBits(GPIOA, GPIO_Pin_2);Delay1us();//36//37     写入了0x65GPIO_SetBits(GPIOA, GPIO_Pin_2);  // CLK=1;Delay1us();GPIO_ResetBits(GPIOA, GPIO_Pin_2); // CLK=0;Delay1us();for(i=0;i<8;i++)// 38 - 45个脉冲了,写8位数据{GPIO_SetBits(GPIOA, GPIO_Pin_2); // CLK=1;Delay1us();if(dat&0x80)GPIO_SetBits(GPIOA, GPIO_Pin_3);// OUT = 1elseGPIO_ResetBits(GPIOA, GPIO_Pin_3);dat <<= 1;GPIO_ResetBits(GPIOA, GPIO_Pin_2);   // CLK=0;Delay1us();}GPIO_SetBits(GPIOA, GPIO_Pin_3);// OUT = 1GPIO_SetBits(GPIOA, GPIO_Pin_2);   // CLK=1;Delay1us();GPIO_ResetBits(GPIOA, GPIO_Pin_2); // CLK=0;Delay1us();
}// 读取芯片的配置数据
unsigned char Read_Config(void)
{unsigned char i;unsigned char dat=0;//读取到的数据unsigned int count_i=0;//溢出计时器
//  unsigned char k=0,j=0;//中间变量OUT_OUT();GPIO_SetBits(GPIOA, GPIO_Pin_3); //OUT引脚拉高OUT_IN();GPIO_ResetBits(GPIOA, GPIO_Pin_2);//时钟拉低while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_3)==1)//等待芯片准备好数据{delay_ms(1);count_i++;if(count_i > 300){OUT_OUT();GPIO_SetBits(GPIOA, GPIO_Pin_2);  // CLK=1;GPIO_SetBits(GPIOA, GPIO_Pin_3);  // OUT=1;return 1;//超时,则直接退出程序}}for(i=0;i<29;i++)// 产生第1到29个时钟{GPIO_SetBits(GPIOA, GPIO_Pin_2);   // CLK=1;Delay1us();GPIO_ResetBits(GPIOA, GPIO_Pin_2); // CLK=0;Delay1us();}OUT_OUT();GPIO_SetBits(GPIOA, GPIO_Pin_2); // CLK=1;Delay1us();GPIO_SetBits(GPIOA, GPIO_Pin_3); GPIO_ResetBits(GPIOA, GPIO_Pin_2); // CLK=0;Delay1us();// 这是第30个时钟GPIO_SetBits(GPIOA, GPIO_Pin_2); // CLK=1;Delay1us();GPIO_ResetBits(GPIOA, GPIO_Pin_3);GPIO_ResetBits(GPIOA, GPIO_Pin_2); // CLK=0;Delay1us();// 这是第31个时钟GPIO_SetBits(GPIOA, GPIO_Pin_2); // CLK=1;Delay1us();GPIO_SetBits(GPIOA, GPIO_Pin_3);GPIO_ResetBits(GPIOA, GPIO_Pin_2); // CLK=0;Delay1us();//32GPIO_SetBits(GPIOA, GPIO_Pin_2); // CLK=1;Delay1us();GPIO_ResetBits(GPIOA, GPIO_Pin_3);GPIO_ResetBits(GPIOA, GPIO_Pin_2); // CLK=0;Delay1us();//33GPIO_SetBits(GPIOA, GPIO_Pin_2); // CLK=1;Delay1us();GPIO_SetBits(GPIOA, GPIO_Pin_3); GPIO_ResetBits(GPIOA, GPIO_Pin_2); // CLK=0;Delay1us();//34GPIO_SetBits(GPIOA, GPIO_Pin_2); // CLK=1;Delay1us();GPIO_SetBits(GPIOA, GPIO_Pin_3);GPIO_ResetBits(GPIOA, GPIO_Pin_2); // CLK=0;Delay1us();//35GPIO_SetBits(GPIOA, GPIO_Pin_2); // CLK=1;Delay1us();GPIO_ResetBits(GPIOA, GPIO_Pin_3);GPIO_ResetBits(GPIOA, GPIO_Pin_2); // CLK=0;Delay1us();//36GPIO_SetBits(GPIOA, GPIO_Pin_3);GPIO_SetBits(GPIOA, GPIO_Pin_2);    // CLK=1;Delay1us();GPIO_ResetBits(GPIOA, GPIO_Pin_2); // CLK=0;Delay1us();//37     写入0x56 即读命令dat=0;OUT_IN();for(i=0;i<8;i++)// 第38 - 45个脉冲了,读取数据{GPIO_SetBits(GPIOA, GPIO_Pin_2); // CLK=1;Delay1us();GPIO_ResetBits(GPIOA, GPIO_Pin_2); // CLK=0;Delay1us();dat <<= 1;if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_3)==1)dat++;}//第46个脉冲GPIO_SetBits(GPIOA, GPIO_Pin_2);    // CLK=1;Delay1us();GPIO_ResetBits(GPIOA, GPIO_Pin_2); // CLK=0;Delay1us();OUT_OUT();GPIO_SetBits(GPIOA, GPIO_Pin_3); //OUT引脚拉高return dat;
}//读取ADC数据,返回的是一个有符号数据
int32_t Read_CS1237(void)
{unsigned char i;uint32_t dat=0;//读取到的数据unsigned int count_i=0;//溢出计时器int32_t temp;OUT_OUT();GPIO_SetBits(GPIOA, GPIO_Pin_3); //OUT引脚拉高OUT_IN();GPIO_ResetBits(GPIOA, GPIO_Pin_2);//时钟拉低while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_3)==1)//等待芯片准备好数据{delay_ms(1);count_i++;if(count_i > 300){OUT_OUT();GPIO_SetBits(GPIOA, GPIO_Pin_2);   // CLK=1;GPIO_SetBits(GPIOA, GPIO_Pin_3);  // OUT=1;return 1;//超时,则直接退出程序}}dat=0;for(i=0;i<24;i++)//获取24位有效转换{GPIO_SetBits(GPIOA, GPIO_Pin_2);  // CLK=1;Delay1us();dat <<= 1;if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_3)==1)dat ++;GPIO_ResetBits(GPIOA, GPIO_Pin_2);  // CLK=0;Delay1us();}for(i=0;i<3;i++)//接着前面的时钟 再来3个时钟{GPIO_SetBits(GPIOA, GPIO_Pin_2);   // CLK=1;Delay1us();GPIO_ResetBits(GPIOA, GPIO_Pin_2); // CLK=0;Delay1us();}OUT_OUT();GPIO_SetBits(GPIOA, GPIO_Pin_3); // OUT = 1;if(dat&0x00800000)// 判断是负数 最高位24位是符号位{temp=-(((~dat)&0x007FFFFF) + 1);// 补码变源码}elsetemp=dat; // 正数的补码就是源码return temp;
}

cs1237.h


#ifndef __CS1237_H
#define __CS1237_H#include "stm32f10x.h"void Delay1us(void);
void Delay1ms(void);
void delay_ms(__IO uint16_t ms);
void CS1237_Init_JX(void);
void CS1237_Config(void);
unsigned char Read_Config(void);
int32_t Read_CS1237(void);#endif

【注:文件源码是Keil uVision5–STM32工程文件】
参考文件源码下载链接:
https://download.csdn.net/download/qq_28056277/11541590
原创文章,转载请注明出处,谢谢。

STM32F103 用CS1237 /HX711 芯片制作电子秤相关推荐

  1. 电子秤HX711芯片使用

    HX711 是一款专用于高精度电子秤而设计的 24 位 A/D 转换器芯片,其内部集成了差分处理电路.稳压电源.片内时钟振荡器等,使电子秤传感器电路大大地简化. HX711芯片主要参数: 工作电压范围 ...

  2. 体重计c语言程序,利用MSP430F149和HX711模块制作体重秤?

    已结贴√ 问题点数:20 回复次数:1 利用MSP430F149和HX711模块制作体重秤? 以下代码是我从另一个论坛大拿那里看来的,如何改动才能只保留数码管显示体重呢?不需要蓝牙模块等等.救救毕设做 ...

  3. 芯片供应商如何看待国际十大芯片制作公司的排名

    芯片供应商如何看待国际十大芯片制作公司的排名 1.英特尔成立于1968年,是一家生产个人电脑部件和制作商.它有50年的市场领导历史.1971年,它推出了第一台微处理器,将计算机和互联网的革新带到了国际 ...

  4. STM32F103操作DS1302时钟芯片串口显示(标准库和HAL库)

    目录 DS1302的性能指标 DS1302的寄存器及片内RAM 标准库实现 HAL库实现 源码链接 单片机型号:STM32F103C8T6 在日常生活中,很多情况下会需要使用时间,单片机中虽然也是有定 ...

  5. 74ls190芯片制作的48进制计数器的计算机图,六十进制计数器综合设计

    <六十进制计数器综合设计>由会员分享,可在线阅读,更多相关<六十进制计数器综合设计(11页珍藏版)>请在人人文库网上搜索. 1.物理与机电工程学院(20152016 学年第 一 ...

  6. 集成芯片制作过程(有图)

    芯片的制造过程可概分为晶圆处理工序(Wafer Fabrication).晶圆针测工序(Wafer Probe).构装工序(Packaging).测试工序(Initial Test and Final ...

  7. 使用Arduino和DS12C887芯片制作电子时钟(附Arduino源代码)

    如何使用Arduino对DS12C887时钟模块进行时间读写 搜了一下DS12C887的资料,最详细的是郭天祥关于这个模块的视频教程,教程中讲解了这个模块的使用手册和程序的编写,但是这个教程是在51单 ...

  8. AT89C51(Atmel)芯片制作简易的频率计

    设计了一个简易的频率计: 51芯片自带2个定时器可以用作定时和计数作用,选择T1作为计数器,去读取高低电平的转换次数.选择T0作为定时器作用,计算1S时间内高低电平的次数,通过算法算出对应的频率.通过 ...

  9. Lm317电压源芯片制作电流源

    文章目录 一.电压源电路 二.电流源电路 三.电流源性能测试-Multisim仿真 3.1.带载能力 3.2.输出电流的稳定性 3.3.输出电流的温度特性 3.4.Load Regulation和Li ...

  10. 基于STM32的HX711模块的电子秤设计

    一.主要功能 打开串口调试助手,波特率设置为115200,系统运行后,蜂鸣器滴一声表示去皮完成,同时串口助手会显示传感器检测实时重量,若重量超过2000g,蜂鸣器报警.当按下KEY1键,物品稳定重量会 ...

最新文章

  1. linux 后台任务 前台任务 查看切换终止开始命令 bg、fg、ctrl+z、ctrl+d和ctrl+c 简介
  2. iview table 自定义列_基于VueJS的render渲染函数打造一款非常强大的IView 的Table组件...
  3. uva 232 Crossword Answers
  4. 有关Silverlight TreeView组件的研究[3]——Silverlight学习笔记(8)
  5. git学习(四)比较文件差异diff
  6. php如何获取li标签中的值,多个 (li) 标签如何获取获取选中的里面的某个特定值??...
  7. Atitit q2016 q5 doc list on home ntpc.docx
  8. java 中如何临时保存某输入值_java笔记临时存放
  9. python的整数类型_python基本数据类型
  10. SGD ,Adam,momentum等优化算法比较
  11. PS CC2018替换/修改图片上的文字内容
  12. 我对网页设计的一点见解!
  13. 电脑通过二维码打开手机链接
  14. 如何利用英特尔管理工具绕过Windows防火墙
  15. 阿里天池大数据竞赛第一名,如何用AI检测肺癌
  16. uni app 自动化索引列表
  17. R语言ggplot2优雅的绘制环状云雨图
  18. 使用飞信API 发送 短信
  19. 京峰网站架构,上线流程
  20. ”核高基“重大专项造成体制浪费就应该取消

热门文章

  1. 集成运算放大器之微分电路搭建
  2. 无人机三维建模(1) 调研
  3. C语言实现FFT算法
  4. Python实现简单p2p下载
  5. cookie登陆qq空间的两种方式
  6. swfupload 无法加载_解决SWFUpload上传控件在非IE浏览器下不好用的问题
  7. 数据库涉及到哪些技术?
  8. Eclipse快捷键的设置和使用(大小写快捷键等)
  9. ssh框架超详细总结
  10. PowerDesign安装教程