STM32F103 用CS1237 /HX711 芯片制作电子秤
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 芯片制作电子秤相关推荐
- 电子秤HX711芯片使用
HX711 是一款专用于高精度电子秤而设计的 24 位 A/D 转换器芯片,其内部集成了差分处理电路.稳压电源.片内时钟振荡器等,使电子秤传感器电路大大地简化. HX711芯片主要参数: 工作电压范围 ...
- 体重计c语言程序,利用MSP430F149和HX711模块制作体重秤?
已结贴√ 问题点数:20 回复次数:1 利用MSP430F149和HX711模块制作体重秤? 以下代码是我从另一个论坛大拿那里看来的,如何改动才能只保留数码管显示体重呢?不需要蓝牙模块等等.救救毕设做 ...
- 芯片供应商如何看待国际十大芯片制作公司的排名
芯片供应商如何看待国际十大芯片制作公司的排名 1.英特尔成立于1968年,是一家生产个人电脑部件和制作商.它有50年的市场领导历史.1971年,它推出了第一台微处理器,将计算机和互联网的革新带到了国际 ...
- STM32F103操作DS1302时钟芯片串口显示(标准库和HAL库)
目录 DS1302的性能指标 DS1302的寄存器及片内RAM 标准库实现 HAL库实现 源码链接 单片机型号:STM32F103C8T6 在日常生活中,很多情况下会需要使用时间,单片机中虽然也是有定 ...
- 74ls190芯片制作的48进制计数器的计算机图,六十进制计数器综合设计
<六十进制计数器综合设计>由会员分享,可在线阅读,更多相关<六十进制计数器综合设计(11页珍藏版)>请在人人文库网上搜索. 1.物理与机电工程学院(20152016 学年第 一 ...
- 集成芯片制作过程(有图)
芯片的制造过程可概分为晶圆处理工序(Wafer Fabrication).晶圆针测工序(Wafer Probe).构装工序(Packaging).测试工序(Initial Test and Final ...
- 使用Arduino和DS12C887芯片制作电子时钟(附Arduino源代码)
如何使用Arduino对DS12C887时钟模块进行时间读写 搜了一下DS12C887的资料,最详细的是郭天祥关于这个模块的视频教程,教程中讲解了这个模块的使用手册和程序的编写,但是这个教程是在51单 ...
- AT89C51(Atmel)芯片制作简易的频率计
设计了一个简易的频率计: 51芯片自带2个定时器可以用作定时和计数作用,选择T1作为计数器,去读取高低电平的转换次数.选择T0作为定时器作用,计算1S时间内高低电平的次数,通过算法算出对应的频率.通过 ...
- Lm317电压源芯片制作电流源
文章目录 一.电压源电路 二.电流源电路 三.电流源性能测试-Multisim仿真 3.1.带载能力 3.2.输出电流的稳定性 3.3.输出电流的温度特性 3.4.Load Regulation和Li ...
- 基于STM32的HX711模块的电子秤设计
一.主要功能 打开串口调试助手,波特率设置为115200,系统运行后,蜂鸣器滴一声表示去皮完成,同时串口助手会显示传感器检测实时重量,若重量超过2000g,蜂鸣器报警.当按下KEY1键,物品稳定重量会 ...
最新文章
- linux 后台任务 前台任务 查看切换终止开始命令 bg、fg、ctrl+z、ctrl+d和ctrl+c 简介
- iview table 自定义列_基于VueJS的render渲染函数打造一款非常强大的IView 的Table组件...
- uva 232 Crossword Answers
- 有关Silverlight TreeView组件的研究[3]——Silverlight学习笔记(8)
- git学习(四)比较文件差异diff
- php如何获取li标签中的值,多个 (li) 标签如何获取获取选中的里面的某个特定值??...
- Atitit q2016 q5 doc list on home ntpc.docx
- java 中如何临时保存某输入值_java笔记临时存放
- python的整数类型_python基本数据类型
- SGD ,Adam,momentum等优化算法比较
- PS CC2018替换/修改图片上的文字内容
- 我对网页设计的一点见解!
- 电脑通过二维码打开手机链接
- 如何利用英特尔管理工具绕过Windows防火墙
- 阿里天池大数据竞赛第一名,如何用AI检测肺癌
- uni app 自动化索引列表
- R语言ggplot2优雅的绘制环状云雨图
- 使用飞信API 发送 短信
- 京峰网站架构,上线流程
- ”核高基“重大专项造成体制浪费就应该取消