Android 基于google Zxing实现二维码、条形码扫描,仿微信二维码扫描效果
这篇文章写的不错,但是按照这篇文章使用二维码的话会出现竖屏扫描图像拉伸变长的问题(有一个地方计算错误),解决拉伸变长的问题后又会出现闪退的问题(传输大Bitmap对象导致闪退,改为Byte数组或者不传递Bitmap)
其他地方不动,即可完美移植二维码扫描功能
改动一:
CameraConfigurationManager文件
findBestPreviewSizeValue方法下边这句
int newDiff = Math.abs(newX - screenResolution.x) + Math.abs(newY - screenResolution.y);
改为
int newDiff=Math.abs(newY - screenResolution.x) + Math.abs(newX - screenResolution.y);
原文那样计算是因为计算的是横屏扫描的分辨率
这样改动后发现扫描不拉伸了,但是没有扫描结果,扫描结果返回的界面一闪而退,是因为Activity之间传递了大的Bitmap
改动二:
MipcaActivityCapture文件
handleDecode方法中将Bitmap转为Byte数组然后再在Activity之间传递或者不传递Bitmap
Intent resultIntent = new Intent(); Bundle bundle = new Bundle(); bundle.putString("result", resultString); // bundle.putParcelable("bitmap", barcode); // ByteArrayOutputStream baos=new ByteArrayOutputStream(); // barcode.compress(Bitmap.CompressFormat.PNG, 100, baos); // byte [] bitmapByte =baos.toByteArray(); // bundle.putByteArray("bitmap",bitmapByte); resultIntent.putExtras(bundle); this.setResult(RESULT_OK, resultIntent);
经过这两处改动,就可以完美使用二维码了
原文还有个问题就是扫描二维码的区域有点小,需要离被扫描的二维码很远才能被扫描
可以参考这篇文章解决此问题:
Android二维码ZXing扫描区域大小的调整,提高扫描速度
原文摘录如下:
转载请注明出处:http://blog.csdn.net/xiaanming/article/details/10163203
了解二维码这个东西还是从微信中,当时微信推出二维码扫描功能,自己感觉挺新颖的,从一张图片中扫一下竟然能直接加好友,不可思议啊,那时候还不了解二维码,呵呵,然后做项目的时候,老板说要加上二维码扫描功能,然后自己的屁颠屁颠的去百度,google啥的,发现很多朋友都有介绍二维码扫描的功能,然后我就跟着人家的介绍自己搞起了二维码扫描功能,跟着人家的帖子,很快我的项目就加入了扫描二维码的功能,然后自己还很开心。
随着微信的到来,二维码越来越火爆,随处能看到二维码,比如商城里面,肯德基,餐厅等等,对于二维码扫描我们使用的是google的开源框架Zxing,我们可以去http://code.google.com/p/zxing/下载源码和Jar包,之前我项目中的二维码扫描功能只实现了扫描功能,其UI真的是其丑无比,一个好的应用软件,其UI界面也要被大众所接纳,不然人家就不会用你的软件啦,所以说应用软件功能和界面一样都很重要,例如微信,相信微信UI被很多应用软件所模仿,我也仿照微信扫描二维码效果进行模仿,虽然没有微信做的那么精致,但是效果还是可以的,所以将自己修改UI的代码和扫描二维码的代码分享给大家,一是自己以后项目遇到同样的功能直接拷贝来用,二是给还没有加入二维码功能的人一个参考,站在巨人的肩膀上,哈哈,我之前也是站在巨人的肩膀上加上此功能,接下来跟着我一步一步来实现此项功能,里面去除了很多不必要的文件
我们先看下项目的结构
- 如果你项目也想加入此功能,你直接将com.mining.app.zxing.camera,com.mining.app.zxing.decoding,com.mining.app.zxing.view这三个包拷贝到你的项目中,然后引入相对应的资源进去,我也是从我的项目中直接引用过来的,包名都没改呢,当然还需要引用Zxing.jar
- com.example.qr_codescan包里面有一个MipcaActivityCapture,也是直接引入我之前项目的代码的,这个Activity主要处理扫描界面的类,比如,扫描成功有声音和振动等等,主要关注里面的handleDecode(Result result, Bitmap barcode)方法,扫描完成之后将扫描到的结果和二维码的bitmap当初参数传递到handleDecode(Result result, Bitmap barcode)里面,我们只需要在里面写出相对应的处理代码即可,其他的地方都不用改得,我这里处理扫描结果和扫描拍的照片
- /**
- * 处理扫描结果
- * @param result
- * @param barcode
- */
- public void handleDecode(Result result, Bitmap barcode) {
- inactivityTimer.onActivity();
- playBeepSoundAndVibrate();
- String resultString = result.getText();
- if (resultString.equals("")) {
- Toast.makeText(MipcaActivityCapture.this, "Scan failed!", Toast.LENGTH_SHORT).show();
- }else {
- Intent resultIntent = new Intent();
- Bundle bundle = new Bundle();
- bundle.putString("result", resultString);
- bundle.putParcelable("bitmap", barcode);
- resultIntent.putExtras(bundle);
- this.setResult(RESULT_OK, resultIntent);
- }
- MipcaActivityCapture.this.finish();
- }
- 我对MipcaActivityCapture界面的布局做了自己的改动,先看下效果图,主要是用到FrameLayout,里面嵌套RelativeLayout,里面的图片也是从微信里面拿出来的,平常我看到需要什么图片就去微信里面找,没有美工的公司的程序员就是苦逼
布局代码如下
- <?xml version="1.0" encoding="utf-8"?>
- <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent" >
- <RelativeLayout
- android:layout_width="fill_parent"
- android:layout_height="fill_parent" >
- <SurfaceView
- android:id="@+id/preview_view"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:layout_gravity="center" />
- <com.mining.app.zxing.view.ViewfinderView
- android:id="@+id/viewfinder_view"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
- <include
- android:id="@+id/include1"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentTop="true"
- layout="@layout/activity_title" />
- </RelativeLayout>
- </FrameLayout>
在里面我将界面上面部分写在另一个布局里面,然后include进来,因为这个activity_title在我项目里面还供其他的Activity使用,我也是直接拷贝出来的
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:background="@drawable/mmtitle_bg_alpha" >
- <Button
- android:id="@+id/button_back"
- android:layout_width="75.0dip"
- android:text="返回"
- android:background="@drawable/mm_title_back_btn"
- android:textColor="@android:color/white"
- android:layout_height="wrap_content"
- android:layout_centerVertical="true"
- android:layout_marginLeft="2dip" />
- <TextView
- android:id="@+id/textview_title"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignBaseline="@+id/button_back"
- android:layout_alignBottom="@+id/button_back"
- android:layout_centerHorizontal="true"
- android:gravity="center_vertical"
- android:text="二维码扫描"
- android:textColor="@android:color/white"
- android:textSize="18sp" />
- </RelativeLayout>
- 在我这个demo里面,有一个主界面MainActivity,里面一个Button, 一个ImageView和一个TextView,点击Button进入到二维码扫描界面,当扫描OK的时候,回到主界面,将扫描的结果显示到TextView,将图片显示到ImageView里面,然后你可以不处理图片,我这里随带的加上图片,主界面的布局很简单如下
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="#ffe1e0de" >
- <Button
- android:id="@+id/button1"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentTop="true"
- android:text="扫描二维码" />
- <TextView
- android:id="@+id/result"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_below="@+id/button1"
- android:lines="2"
- android:gravity="center_horizontal"
- android:textColor="@android:color/black"
- android:textSize="16sp" />
- <ImageView
- android:id="@+id/qrcode_bitmap"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:layout_alignParentLeft="true"
- android:layout_below="@+id/result"/>
- </RelativeLayout>
- MainActivity里面的代码如下,里面的功能在上面已经说了
- package com.example.qr_codescan;
- import android.app.Activity;
- import android.content.Intent;
- import android.graphics.Bitmap;
- import android.os.Bundle;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.widget.Button;
- import android.widget.ImageView;
- import android.widget.TextView;
- public class MainActivity extends Activity {
- private final static int SCANNIN_GREQUEST_CODE = 1;
- /**
- * 显示扫描结果
- */
- private TextView mTextView ;
- /**
- * 显示扫描拍的图片
- */
- private ImageView mImageView;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- mTextView = (TextView) findViewById(R.id.result);
- mImageView = (ImageView) findViewById(R.id.qrcode_bitmap);
- //点击按钮跳转到二维码扫描界面,这里用的是startActivityForResult跳转
- //扫描完了之后调到该界面
- Button mButton = (Button) findViewById(R.id.button1);
- mButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- Intent intent = new Intent();
- intent.setClass(MainActivity.this, MipcaActivityCapture.class);
- intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
- startActivityForResult(intent, SCANNIN_GREQUEST_CODE);
- }
- });
- }
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- super.onActivityResult(requestCode, resultCode, data);
- switch (requestCode) {
- case SCANNIN_GREQUEST_CODE:
- if(resultCode == RESULT_OK){
- Bundle bundle = data.getExtras();
- //显示扫描到的内容
- mTextView.setText(bundle.getString("result"));
- //显示
- mImageView.setImageBitmap((Bitmap) data.getParcelableExtra("bitmap"));
- }
- break;
- }
- }
- }
- 上面的代码还是比较简单,但是要想做出像微信那样只的扫描框,紧紧上面的代码是没有那种效果的,我们必须重写com.mining.app.zxing.view包下面的ViewfinderView类,微信里面的都是用的图片,我是自己画出来的,代码注释的比较清楚,大家直接看代码吧,相信你能理解的,如果你要修改扫描框的大小,去CameraManager类里面修改
- /*
- * Copyright (C) 2008 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package com.mining.app.zxing.view;
- import java.util.Collection;
- import java.util.HashSet;
- import android.content.Context;
- import android.content.res.Resources;
- import android.graphics.Bitmap;
- import android.graphics.Canvas;
- import android.graphics.Color;
- import android.graphics.Paint;
- import android.graphics.Rect;
- import android.graphics.Typeface;
- import android.util.AttributeSet;
- import android.view.View;
- import com.example.qr_codescan.R;
- import com.google.zxing.ResultPoint;
- import com.mining.app.zxing.camera.CameraManager;
- /**
- * This view is overlaid on top of the camera preview. It adds the viewfinder
- * rectangle and partial transparency outside it, as well as the laser scanner
- * animation and result points.
- *
- */
- public final class ViewfinderView extends View {
- private static final String TAG = "log";
- /**
- * 刷新界面的时间
- */
- private static final long ANIMATION_DELAY = 10L;
- private static final int OPAQUE = 0xFF;
- /**
- * 四个绿色边角对应的长度
- */
- private int ScreenRate;
- /**
- * 四个绿色边角对应的宽度
- */
- private static final int CORNER_WIDTH = 10;
- /**
- * 扫描框中的中间线的宽度
- */
- private static final int MIDDLE_LINE_WIDTH = 6;
- /**
- * 扫描框中的中间线的与扫描框左右的间隙
- */
- private static final int MIDDLE_LINE_PADDING = 5;
- /**
- * 中间那条线每次刷新移动的距离
- */
- private static final int SPEEN_DISTANCE = 5;
- /**
- * 手机的屏幕密度
- */
- private static float density;
- /**
- * 字体大小
- */
- private static final int TEXT_SIZE = 16;
- /**
- * 字体距离扫描框下面的距离
- */
- private static final int TEXT_PADDING_TOP = 30;
- /**
- * 画笔对象的引用
- */
- private Paint paint;
- /**
- * 中间滑动线的最顶端位置
- */
- private int slideTop;
- /**
- * 中间滑动线的最底端位置
- */
- private int slideBottom;
- private Bitmap resultBitmap;
- private final int maskColor;
- private final int resultColor;
- private final int resultPointColor;
- private Collection<ResultPoint> possibleResultPoints;
- private Collection<ResultPoint> lastPossibleResultPoints;
- boolean isFirst;
- public ViewfinderView(Context context, AttributeSet attrs) {
- super(context, attrs);
- density = context.getResources().getDisplayMetrics().density;
- //将像素转换成dp
- ScreenRate = (int)(20 * density);
- paint = new Paint();
- Resources resources = getResources();
- maskColor = resources.getColor(R.color.viewfinder_mask);
- resultColor = resources.getColor(R.color.result_view);
- resultPointColor = resources.getColor(R.color.possible_result_points);
- possibleResultPoints = new HashSet<ResultPoint>(5);
- }
- @Override
- public void onDraw(Canvas canvas) {
- //中间的扫描框,你要修改扫描框的大小,去CameraManager里面修改
- Rect frame = CameraManager.get().getFramingRect();
- if (frame == null) {
- return;
- }
- //初始化中间线滑动的最上边和最下边
- if(!isFirst){
- isFirst = true;
- slideTop = frame.top;
- slideBottom = frame.bottom;
- }
- //获取屏幕的宽和高
- int width = canvas.getWidth();
- int height = canvas.getHeight();
- paint.setColor(resultBitmap != null ? resultColor : maskColor);
- //画出扫描框外面的阴影部分,共四个部分,扫描框的上面到屏幕上面,扫描框的下面到屏幕下面
- //扫描框的左边面到屏幕左边,扫描框的右边到屏幕右边
- canvas.drawRect(0, 0, width, frame.top, paint);
- canvas.drawRect(0, frame.top, frame.left, frame.bottom + 1, paint);
- canvas.drawRect(frame.right + 1, frame.top, width, frame.bottom + 1,
- paint);
- canvas.drawRect(0, frame.bottom + 1, width, height, paint);
- if (resultBitmap != null) {
- // Draw the opaque result bitmap over the scanning rectangle
- paint.setAlpha(OPAQUE);
- canvas.drawBitmap(resultBitmap, frame.left, frame.top, paint);
- } else {
- //画扫描框边上的角,总共8个部分
- paint.setColor(Color.GREEN);
- canvas.drawRect(frame.left, frame.top, frame.left + ScreenRate,
- frame.top + CORNER_WIDTH, paint);
- canvas.drawRect(frame.left, frame.top, frame.left + CORNER_WIDTH, frame.top
- + ScreenRate, paint);
- canvas.drawRect(frame.right - ScreenRate, frame.top, frame.right,
- frame.top + CORNER_WIDTH, paint);
- canvas.drawRect(frame.right - CORNER_WIDTH, frame.top, frame.right, frame.top
- + ScreenRate, paint);
- canvas.drawRect(frame.left, frame.bottom - CORNER_WIDTH, frame.left
- + ScreenRate, frame.bottom, paint);
- canvas.drawRect(frame.left, frame.bottom - ScreenRate,
- frame.left + CORNER_WIDTH, frame.bottom, paint);
- canvas.drawRect(frame.right - ScreenRate, frame.bottom - CORNER_WIDTH,
- frame.right, frame.bottom, paint);
- canvas.drawRect(frame.right - CORNER_WIDTH, frame.bottom - ScreenRate,
- frame.right, frame.bottom, paint);
- //绘制中间的线,每次刷新界面,中间的线往下移动SPEEN_DISTANCE
- slideTop += SPEEN_DISTANCE;
- if(slideTop >= frame.bottom){
- slideTop = frame.top;
- }
- canvas.drawRect(frame.left + MIDDLE_LINE_PADDING, slideTop - MIDDLE_LINE_WIDTH/2, frame.right - MIDDLE_LINE_PADDING,slideTop + MIDDLE_LINE_WIDTH/2, paint);
- //画扫描框下面的字
- paint.setColor(Color.WHITE);
- paint.setTextSize(TEXT_SIZE * density);
- paint.setAlpha(0x40);
- paint.setTypeface(Typeface.create("System", Typeface.BOLD));
- canvas.drawText(getResources().getString(R.string.scan_text), frame.left, (float) (frame.bottom + (float)TEXT_PADDING_TOP *density), paint);
- Collection<ResultPoint> currentPossible = possibleResultPoints;
- Collection<ResultPoint> currentLast = lastPossibleResultPoints;
- if (currentPossible.isEmpty()) {
- lastPossibleResultPoints = null;
- } else {
- possibleResultPoints = new HashSet<ResultPoint>(5);
- lastPossibleResultPoints = currentPossible;
- paint.setAlpha(OPAQUE);
- paint.setColor(resultPointColor);
- for (ResultPoint point : currentPossible) {
- canvas.drawCircle(frame.left + point.getX(), frame.top
- + point.getY(), 6.0f, paint);
- }
- }
- if (currentLast != null) {
- paint.setAlpha(OPAQUE / 2);
- paint.setColor(resultPointColor);
- for (ResultPoint point : currentLast) {
- canvas.drawCircle(frame.left + point.getX(), frame.top
- + point.getY(), 3.0f, paint);
- }
- }
- //只刷新扫描框的内容,其他地方不刷新
- postInvalidateDelayed(ANIMATION_DELAY, frame.left, frame.top,
- frame.right, frame.bottom);
- }
- }
- public void drawViewfinder() {
- resultBitmap = null;
- invalidate();
- }
- /**
- * Draw a bitmap with the result points highlighted instead of the live
- * scanning display.
- *
- * @param barcode
- * An image of the decoded barcode.
- */
- public void drawResultBitmap(Bitmap barcode) {
- resultBitmap = barcode;
- invalidate();
- }
- public void addPossibleResultPoint(ResultPoint point) {
- possibleResultPoints.add(point);
- }
- }
上面的代码中,中间那根线微信是用的图片,我这里是画的,如果你想更加仿真点就将下面的代码
- canvas.drawRect(frame.left + MIDDLE_LINE_PADDING, slideTop - MIDDLE_LINE_WIDTH/2, frame.right - MIDDLE_LINE_PADDING,slideTop + MIDDLE_LINE_WIDTH/2, paint);
改成
- Rect lineRect = new Rect();
- lineRect.left = frame.left;
- lineRect.right = frame.right;
- lineRect.top = slideTop;
- lineRect.bottom = slideTop + 18;
- canvas.drawBitmap(((BitmapDrawable)(getResources().getDrawable(R.drawable.qrcode_scan_line))).getBitmap(), null, lineRect, paint);
那条扫描线自己去微信里面找一下,我贴出来的失真了,下载微信apk,将后缀名改成zip,然后解压就行了
画扫描框下面字体的代码需要修改下,这样子能根据字体自动排列在中间,如果字太长我没有处理,那个要自动换行,你可以自行处理
- paint.setColor(Color.WHITE);
- paint.setTextSize(TEXT_SIZE * density);
- paint.setAlpha(0x40);
- paint.setTypeface(Typeface.DEFAULT_BOLD);
- String text = getResources().getString(R.string.R.string.scan_text);
- float textWidth = paint.measureText(text);
- canvas.drawText(text, (width - textWidth)/2, (float) (frame.bottom + (float)TEXT_PADDING_TOP *density), paint)
运行界面截图,其中中间的那根绿色的线会上下移动,跟微信的效果差不多,当然运行你还需要相对应的权限问题,有兴趣的朋友可以去下载demo
从8点多写这篇博客写到现在,看起来这么点字,但实际上还是比较耗时间的,如果你觉得这篇文章对你有帮助,你就顶一下,哈哈,洗澡睡觉去了,上面的项目中还有一些资源文件我没有贴出来,想要看效果可以下载源码
我在Android 基于google Zxing实现对手机中的二维码进行扫描这篇文章中实现了对手机中二维码照片的扫描,并且替换了中间的扫描线,和微信效果更加相似,建议大家去下那文章的项目源码
相关推荐
这篇文章写的不错,但是按照这篇文章使用二维码的话会出现竖屏扫描图像拉伸变长的问题(有一个地方计算错误),解决拉伸变长的问题后又会出现闪退的问题(传输大Bitmap对象导致闪退,改为Byte数组或者不传递Bitmap)...
内容概要:本文详细介绍了雅马哈机械手在锁螺丝过程中与视觉系统的协同工作流程,重点讲解了Socket通信的实现方法、坐标转换的具体步骤以及动态路径规划的技术细节。首先,文章展示了如何通过TCP/IP协议建立机械手与相机之间的稳定通信,确保数据传输的可靠性和实时性。接着,深入探讨了从像素坐标到机械臂笛卡尔坐标的转换过程,强调了标定矩阵的重要性和正确处理字节序的问题。此外,还讨论了托盘动态路径规划的实现,如螺旋式搜索算法的应用及其带来的效率提升。最后,文章分享了一些实际应用中的经验和教训,如处理粘包问题、网络延迟、异常处理机制等。 适合人群:从事工业自动化领域的工程师和技术人员,尤其是对机械手与视觉系统集成感兴趣的读者。 使用场景及目标:适用于需要深入了解机械手与视觉系统协作机制的场合,帮助工程师更好地理解和优化工业生产线上的自动化设备。目标是提高生产效率和产品质量,减少因技术问题导致的生产停滞。 其他说明:文中提供了多个代码示例,涵盖Python、C++和C#等多种编程语言,便于不同背景的读者参考和实践。同时,作者结合自身经验,给出了许多实用的调试技巧和注意事项,有助于读者规避常见错误并快速解决问题。
内容概要:本文详细介绍了如何利用LabVIEW与西门子S7-200 PLC通过PPI协议进行通讯的方法和技术要点。主要内容涵盖硬件准备、通讯参数配置、PPI协议命令格式、命令发送与接收、数据解析以及常见问题的调试方法。文中强调了硬件选择、波特率设置、命令帧结构、CRC校验、超时处理等方面的具体操作步骤,并提供了多个实用技巧,如地址扫描、批量读取优化、字节序处理等。 适合人群:从事工业自动化系统集成、LabVIEW编程、PLC通讯开发的技术人员。 使用场景及目标:适用于需要将LabVIEW与西门子S7-200 PLC进行通讯的工程项目,帮助技术人员快速掌握PPI协议的应用,提高通讯稳定性和效率。 其他说明:文章不仅提供了详细的理论指导,还分享了许多实践经验,有助于解决实际应用中的各类问题。
计算机二级考试资源合集:高效备考,轻松通关! 本合集涵盖计算机二级考试核心内容,包括软件/硬件知识、编程、数据库、网络技术等,提供理论资料与实战资源(如PHP示例、网页文件、配置数据等),助你系统复习、强化实操。适合考生快速提升技能,顺利通过考试!
内容概要:本文档提供了基于STM32的宠物饮水机的C++源代码,实现了循环过滤和保持水质清洁的功能。代码包括硬件初始化、水位检测、温度监测、紫外线杀菌以及OLED显示等功能模块。通过水位传感器检测水位并控制水泵启停,使用DS18B20温度传感器监测水温并在OLED屏幕上显示,每小时自动启动紫外线灯进行杀菌5分钟。此外,详细解释了水位传感器的工作原理及其在代码中的实现,重点介绍了浮球式传感器的结构和工作过程。 适合人群:对嵌入式系统开发有一定了解,特别是熟悉STM32平台和C++编程的工程师或爱好者。 使用场景及目标:①学习STM32平台下的硬件初始化和外设驱动编程;②掌握水位传感器、温度传感器及紫外线杀菌功能的设计与实现;③理解浮球式水位传感器的工作原理及其在实际项目中的应用。 阅读建议:此资源不仅提供了完整的源代码,还详细解释了每个功能模块的实现细节,适合在实际项目中参考和学习。建议读者结合STM32开发板进行实践操作,深入理解各个功能模块的工作机制,并根据具体需求进行功能扩展和优化。
语音模块的打印文件,直接使用。
内容概要:本文档是傲拓科技股份有限公司发布的NA200H可编程控制器(PLC)硬件手册,旨在详细介绍NA200H系列PLC的硬件特性、安装、拆卸与接线原则。NA200H系列PLC是一款小型一体化PLC,具有集成以太网接口,适用于恶劣运行环境,具备良好的扩展性能和低廉的价格。手册涵盖了NA200H PLC的硬件组成(包括CPU模块和各种扩展模块)、工作方式、编程软件介绍、快速应用指南以及详细的安装、拆卸与接线原则。此外,手册还提供了CPU模块和各类I/O扩展模块的技术参数、端子定义与接线说明,并介绍了多种通讯模块的功能和特性。最后,附录部分列出了订货参数和扩展模块的功率消耗清单。 适合人群:具备一定电气知识的操作人员和技术人员,特别是从事自动化控制系统设计、安装和维护的工程师。 使用场景及目标:①帮助用户了解NA200H PLC的硬件结构和工作原理;②指导用户正确安装、配置和维护NA200H PLC;③协助用户选择合适的扩展模块以满足特定的应用需求;④提供详细的接线和通讯配置指导,确保系统稳定运行。 阅读建议:本手册内容详尽,建议读者在使用产品前仔细阅读并理解相关内容,尤其是安装、拆卸和接线部分,以确保系统的安全和稳定运行。同时,建议结合实际应用场景,灵活运用手册中的信息,进行合理的系统设计和配置。
电脑手机端全新UI界面优化更新 支持PC+wap端自动识别跳转 代码工整易于阅读,方便二次修改 全站幻灯片后台自定义更换 大部分可见数据后台可自行修改配置 栏目结构层次清晰,非常利于搜索引擎优化 服务器环境:PHP>=5.3,支持最新的PHP7 系统默认采用Sqlite数据库,放入PHP(5.3+)环境即可直接使用, 系统独家支持七牛云对接,无论你是否启用七牛云,请把轮播图,栏目大图,定制标签内的部分图片重新上传可直接保存图 片,重新上传一下,否则不会图片可能会不显示(因为那些图片在我们的七牛云内) 授权码生成:https://www.pbootcms.com/freesn/ 默认采用sqlite数据库,不需要做导入和配置操作 为了网站各个页面正常运行,请不要修改URL规则 统计代码、商桥代码、各种客服代码,均可放置在后台统计位置,全站生效。 浏览器标签logo在根目录favicon.ico,ico格式百度一下,可以生成 后台地址:您的域名/admin.php 账号:admin密码:123456789
甲壳虫adb助手安全下载.apk
内容概要:本文档《1_蓝桥杯省赛考点整合.pdf》详细介绍了蓝桥杯省赛中常见的硬件模块及其编程实现方法。主要包括Led模块、Key模块、Seg模块、ds1302、ds18b20、PCF8591、EEPROM、超声波模块、串口通信、NE555定时器以及蜂鸣器继电器的底层代码和具体应用实例。每个模块都涵盖了代码示例、功能解释及具体的省赛题目应用场景。例如Led模块展示了如何根据模式显示Led、Led闪烁和PWM亮度调整;Key模块讲解了模式切换、参数设置和按键长按短按等功能;Seg模块则侧重于正常数据显示和闪烁效果。
内容概要:本文详细介绍了基于Matlab的图像拼接GUI系统的实现过程,涵盖了五个主要模块:系统管理、角点提取(Harris角点)、特征匹配(SIFT匹配)、匹配优化(RANSAC)和图像拼接(单映变换)。系统管理模块负责初始化环境和参数设置;角点提取模块使用Harris角点算法识别图像的关键点;特征匹配模块通过SIFT算法寻找匹配点对;匹配优化模块采用RANSAC算法去除误匹配点;最终图像拼接模块利用单映变换完成图像融合。文中还提供了大量代码示例和参数调优技巧,如高斯滤波的sigma值选择、SIFT匹配阈值设定、RANSAC迭代次数和像素容差调整等。 适合人群:对图像处理感兴趣的初学者和有一定编程基础的研究人员。 使用场景及目标:适用于学习和研究图像拼接技术,尤其是希望通过Matlab实现图像处理算法的人群。目标是掌握图像拼接的基本原理和技术实现,能够独立构建类似的图像处理系统。 其他说明:文中提供的代码仅供学习参考,实际应用中建议进一步优化和改进。同时,文中提及了一些实用技巧,如内存管理和性能优化,有助于提高系统的稳定性和效率。
内容概要:本文详细介绍了基于西门子S7-200 Smart PLC的30吨双级反渗透水处理系统的设计与实现。主要内容涵盖了一键制水、加药控制、触摸屏组态、程序结构优化等方面的技术细节。文中不仅展示了具体的PLC梯形图代码片段,还分享了许多现场调试的经验和技巧,如定时器防抖、中断优先处理、PID闭环控制的应用等。此外,文章还提到了一些实用的功能设计,如无人值守模式的安全机制、长按按钮触发高级设置等。 适合人群:从事水处理自动化系统设计、维护的工程师和技术人员,尤其是熟悉西门子PLC编程的从业者。 使用场景及目标:适用于需要稳定产水的工业应用场景,帮助工程师理解和掌握双级反渗透系统的控制逻辑,提高系统的可靠性和效率。同时,也为新手提供了宝贵的调试经验和注意事项。 其他说明:文章强调了程序结构的模块化设计,便于后期维护和参数调整。建议读者结合提供的工程文件进行仿真练习,以便更好地理解系统的工作原理。
内容概要:本文详细介绍了基于LabVIEW 2018版开发的多路温度采集系统,涵盖了系统架构设计、Modbus通讯实现、FGV(功能性全局变量)应用、队列管理和引用控制等多个高级知识点。系统采用了一主两从的串口连接方式,其中一个从机负责温度采集,另一个从机负责开关控制。文中提供了具体的代码示例,如串口配置、Modbus主站配置、数据读取、FGV创建与使用、队列操作等,展示了如何通过这些技术实现高效的数据传输和处理。 适用人群:适用于有一定LabVIEW基础的研发人员和技术爱好者,尤其是希望深入理解LabVIEW高级特性和Modbus通讯机制的人群。 使用场景及目标:①掌握LabVIEW中Modbus通讯的具体实现方法;②学会使用FGV实现跨VI的数据共享;③理解队列在多线程数据处理中的应用;④熟悉引用控制在动态界面更新中的作用。通过这些技术的应用,可以提高项目的开发效率和系统的稳定性。 其他说明:本文不仅提供了详细的代码示例,还分享了许多实践经验,如如何避免内存泄漏、如何处理异常情况等。此外,作者还强调了系统架构的设计思路,如分层设计、生产者-消费者模式等,这些都是实际项目开发中非常重要的考虑因素。
RAG-N算法,滤波器加法器优化代码
《软考软件设计师高频考点精析》精准提炼考试核心内容,涵盖编程语言、数据结构、操作系统、数据库、软件工程等必考领域。结合历年真题与实战技巧,助你快速掌握重点,高效备考。一册在手,轻松攻克软考难关!
内容概要:本文详细介绍了如何利用LabVIEW和周立功库文件构建一个能够进行基本CAN通讯的上位机系统。主要内容涵盖前期准备工作,包括安装LabVIEW软件和下载相关库文件;创建LabVIEW项目,调用库文件实现CAN设备初始化、数据发送与接收等功能的具体步骤;以及一些常见的注意事项和避坑指南。此外,还提供了进阶玩法,如封装成子VI、优化接收处理逻辑等。 适合人群:适用于初次接触LabVIEW和CAN通讯的技术爱好者,尤其是希望快速掌握CAN通讯上位机开发的初学者。 使用场景及目标:本教程旨在帮助用户建立一个简易的CAN通讯平台,以便于后续深入研究或实际项目开发。通过动手实践,读者将学会如何配置CAN设备、编写数据传输代码,并理解CAN通讯的基本原理。 其他说明:文中附带了详细的代码示例和实用技巧,有助于提高学习效率。同时强调了正确配置结构体成员顺序、管理设备句柄、匹配波特率等关键点,以确保系统的稳定性。
内容概要:本文详细介绍了永磁同步电机(PMSM)矢量控制的C代码实现,涵盖从理论到实践的全过程。首先解释了矢量控制的基本原理,即通过坐标变换将三相电流解耦为励磁电流和转矩电流,以便独立控制电机的转矩和磁通。接着介绍了S-function模式仿真的优势,强调它可以灵活嵌入自定义代码并与其他Simulink模块协同工作。文中提供了关键的C代码示例,包括电机参数和状态变量的初始化、Clark变换和Park变换的具体实现、PI控制器的设计以及SVPWM生成算法。此外,还讨论了代码移植到实际工程项目中的注意事项,如硬件资源对接、参数调整和优化技巧。 适合人群:从事电机控制系统开发的技术人员,尤其是有一定C语言编程基础并对永磁同步电机矢量控制感兴趣的工程师。 使用场景及目标:适用于希望深入了解永磁同步电机矢量控制原理并在实际项目中应用相关技术的研发人员。主要目标是帮助读者掌握从仿真到实际应用的完整流程,提高电机控制系统的开发效率和稳定性。 其他说明:文中不仅提供了详细的代码示例,还分享了许多来自实际项目的宝贵经验和技术细节,如定点运算优化、锁相环(PLL)实现中的常见问题及解决方案、PI控制器的抗积分饱和处理等。这些内容对于理解和解决实际开发中的难题非常有帮助。
流变学在材料科学中的应用:聚合物流变学仿真.zip
内容概要:本文详细介绍了如何使用LabVIEW与三菱FX系列PLC进行编程口协议通讯。首先解释了协议的基本结构,包括起始符、结束符、ASCII字符指令以及校验码的计算方式。接着展示了具体的LabVIEW代码实现,涵盖了串口配置、命令帧构造、数据解析等关键步骤。文中还分享了许多实用技巧和常见错误的解决方案,如正确设置串口参数、处理特殊字符、优化读取速度等。此外,作者提供了完整的工程源码,并强调了在实际应用中需要注意的问题,如通信间隔控制和浮点数处理。 适合人群:从事工业自动化领域的工程师和技术人员,特别是熟悉LabVIEW和三菱PLC的用户。 使用场景及目标:适用于需要通过编程口与三菱FX系列PLC进行通讯的应用场景,如读取寄存器数据、监控设备状态等。目标是帮助读者掌握LabVIEW与三菱PLC通讯的具体实现方法,提高工作效率。 其他说明:文中提到的所有代码和技巧均经过实际验证,确保可行性和可靠性。建议读者在实践中结合自己的具体需求进行调整和优化。