C51 单片机编程模板及编码规范

文章目录

  • 一、C51 单片机模板创建
    • 1. 新建工程及选型
    • 2. 创建主程序文件
    • 3. 创建主程序的头文件
    • 4. 编译配置
    • 5. 其他
  • 二、C51 的编码规范

在这里插入图片描述

在查阅了很多关于 C51 单片机的程序后,个人感觉目前网上有关 C51 单片机程序的质量参差不齐,很多程序的代码风格及其糟糕,可读性也很差1。除了新手如此,很多写了多年程序的程序员老手也如此,也包括笔者还处于新手期的时候,在在乎程序是否可以正常运行,而忽略了程序的可读性、可维护性、可复用性以及可扩展性。

由于工作时,笔者所在的公司在编码风格和规范上有及其严格的规定,所以决定总结一下我对我在编写 C51 单片机程序时的编码规范。本文以猿学社上官一号开发板(核心为 STC89C52RC)为基础而编写,编码风格为 K&R(笔者之前干的是 Linux 内核驱动开发,工作用的就是这个风格),变量和函数使用下划线命名法。

在这里插入图片描述

本文前置要求:

  1. 已安装了 C51 的开发环境 Keil uVision5,未安装的建议参考博客《Keil MDK 与 Keil C51 共存的方法》,该文同时安装了 STM32 等主流 32 位单片机的开发环境,并解决了两个软件的共存问题。
  2. 下载 C51 单片机的烧录工具,软件下载地址:工具软件 STC-ISP

一、C51 单片机模板创建

模板的好处在于新建项目时,可以省去选型、添加必要文件等步骤,只要是同一个芯片的项目,复制模板后就可以直接开始编码工作。

模板已同步到 GitHub 和 Gitee,欢迎指正和查阅。

GitHub 链接

Gitee 链接

1. 新建工程及选型

运行 Keil uVision5,在最上面的菜单找到 Project 并点击,弹出下拉菜单后,选择第一个 New μVision Project

在这里插入图片描述

随后的弹窗中,为存放项目的文件夹,我个人的习惯是将所有的代码都放在一个名为 Code 的文件夹中,在里面再具体分类是什么类型的代码,如果是 C51 的代码会专门新建一个文件夹来存放,这里为了演示,直接在 D 盘新建了 C51 的文件夹。然后在文件夹中再新建一个文件夹,名为 template,也就是模板的意思,双击进入文件夹,在下方的文件名再次输入 template,点击 保存

在这里插入图片描述

接着是选型弹窗,由于我的 Keil 包含了 MDK 版本,所以在选型时要先切换到 Legacy Device Database(意思是旧设备数据库),然后按下图操作即可。这里解释一下为什么选择 89C52,而不是 89C51,首先这两者的架构是一样的,都是 Intel 8051 架构,而上官一号采用的芯片是 STC89C52RC,故选 89C52;其次,C52 比 C51 多个更多的外设,例如,C51 拥有 4KB 的 ROM 作为程序存储空间,而 C52 是更大的 8KB,C51 只有两个 16 位定时器/计数器(T0 和 T1),而 C52 多一个额外的 16 位定时器/计数器(T2)等等。当然了,选择 89C51 也可能正常编译程序,并烧录进单片机运行,只是通常会选择与芯片相同的型号最佳。

在这里插入图片描述

不过这里也有人注意到了,现在的 C51 单片机基本都是 STC 生产的(深圳宏晶科技),为什么可以用 AT89C52 来代替 STC89C52 呢?其实这个无所谓选哪个,只要是 89C52 都可以,反正架构是一样的就行。

选好芯片型号后,在随后的弹窗中选择 ,不然程序不能正常编译,这是 C51 的启动文件。

在这里插入图片描述

2. 创建主程序文件

在左边的项目侧边栏中,逐级点开 Target 1 -> Source Group 1,然后鼠标右键点击 Source Group 1,在弹出的菜单中选择 Add New Item to Group 'Source Group 1'

在这里插入图片描述

在随后的弹窗中,按下图所示操作,目的是创建 main.c 作为主程序文件。

在这里插入图片描述

创建成功后,输入下面的代码作为基础模板。

/********************************************************************
 * File: 
 * Description: 
 * Version: 
 * Date: 
 * Author: 
 * ---------- Revision History ----------
 * <version> <date> <author> <desc>
 * 
 ********************************************************************/

#include "main.h"

/* User Code Includes */

/* User Code Define */

/* User Code Global Variables */

/* User Code Function prototypes */


/* ------------------------------ Division Line ------------------------------ */

/**
 * @brief Initialize all configured.
 */
void setup(void)
{
    /* put your setup code here, to run once: */
    
}

/**
 * @brief The application entry point.
 */
void main(void)
{
    /* Private variables */
    
    /* Initialize */
    setup();
	/* Infinite loop */
    while (TRUE){
        /* put your main code here, to run repeatedly: */
        
    }
}

简单说明以下这个代码框架的含义,熟悉 Arduino 的同学应该一眼就看出我是抄了 Arduino IDE 的默认程序框架,setup() 是用于做初始化的函数,这个函数只运行一次,后面主要用于循环执行的程序则放在 mian() 函数中的 while(TRUE) 里。其他的注释基本是参考 CubeMX 生成的 Keil 代码,具体解释如下:

  • /* User Code Includes */:在这个注释下可以添加其他头文件。
  • /* User Code Define */:在这个注释下添加程序需要的宏定义。
  • /* User Code Global Variables */:在这个注释下添加全局变量。
  • /* User Code Function prototypes */:在这个注释下添加函数原型。
  • /* Private variables */main() 函数中还有 /* Private variables */,由于 C51 采用的是 C90 的编码标准,所有局部变量都只能写在函数最前端,故设此注释,可在此注释下添加 main() 函数的局部变量。

最前面的一大块注释是文件的描述,这个后面再做具体的解释,当前效果如下图:

![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=.%2Fassets%2F在这里插入图片描述
pos_id=img-OJgPGQ6k-1715657159591)

3. 创建主程序的头文件

相信大家也都注意到了,在主文件中的 main.h 头文件目前是不存在的,以及 while 循环的条件是 TRUE,这个也是目前不存在的变量或宏定义,所以接下来就要创建对应的头文件。

与创建 .c 文件差不多,创建头文件只需要选择 Header File(.h) 即可。

在这里插入图片描述

然后在 main.h 文件中输入以下代码:

/********************************************************************
 * File: bit.h
 * Description: 89C51/89C52 main header files.
 * Version: 1.0
 * Date: 2024-04-25
 * Author: zhengxinyu13@gmail.com
 * ---------- Revision History ----------
 * <version> <date> <author> <desc>
 * 
 ********************************************************************/

#ifndef __MAIN_H__
#define __MAIN_H__

#include "STC89C5xRC-rdp.h"

#define HIGH        1
#define LOW         0
#define TRUE        1
#define FALSE       0
#define TURN_ON     1
#define TURN_OFF    0

#define SET(pin)    (pin) = 1
#define RESET(pin)  (pin) = 0

typedef unsigned char   uint8_t;
typedef signed char     int8_t;
typedef unsigned int    uint16_t;
typedef signed int      int16_t;
typedef unsigned long   uint32_t;
typedef signed long     int32_t;

#include "delay.h"

#endif // __MAIN_H__

整个头文件用 #ifndef #define #endif 的结构,可以防止重复定义。__MAIN_H__ 这个宏的命名方式也是行业约定俗成的命名方法,两个下划线开头,然后就是头文件名字的大写,中间的点用下划线代替,再两个下划线结尾。#endif 最后都会习惯用双斜杠注释最开始定义的宏,表示这个 #endif 是从哪个 #ifndef 开始的。

中间是一些常用的宏定义,typedef 关键字后面重定义了一些数据类型,这些类型别名使得代码更加可读,并且有助于提升代码的可移植性。这些数据类型取自 <stdint.h> 这个头文件,但是因为 C51 单片机使用的还是 C90 的标准,该头文件为 C99 标准时引入的头文件,因此没办法在这插入,所以才使用了typedef 关键字进行重定义。

regx51.h 头文件是 Keil 安装时就已经引入,不需要用户自定义,但是这个头文件并不完整,例如像特殊寄存器 AUXR、WDT_CONTR 等都未定义,也没有定义 P4 引脚,所以 STC89C5xRC-rdp.h 头文件对此进行了补充,该文件非笔者编写,而是由烧录软件 STC-ISP 自动生成。

在这里插入图片描述

具体代码如下:

/*--------------------------------------------------------------------------
STC89C5xRC-rdp.h

Supplemental header files for Low Voltage Flash Atmel AT89C52 and AT89LV52.
--------------------------------------------------------------------------*/

#ifndef __STC89C5xRC_RDP_H__
#define __STC89C5xRC_RDP_H__

/

//包含本头文件后,不用另外再包含"REG51.H"

sfr         P0          =           0x80;
    sbit    P00         =           P0^0;
    sbit    P01         =           P0^1;
    sbit    P02         =           P0^2;
    sbit    P03         =           P0^3;
    sbit    P04         =           P0^4;
    sbit    P05         =           P0^5;
    sbit    P06         =           P0^6;
    sbit    P07         =           P0^7;

sfr         SP          =           0x81;
sfr         DPL         =           0x82;
sfr         DPH         =           0x83;
sfr         PCON        =           0x87;

sfr         TCON        =           0x88;
    sbit    TF1         =           TCON^7;
    sbit    TR1         =           TCON^6;
    sbit    TF0         =           TCON^5;
    sbit    TR0         =           TCON^4;
    sbit    IE1         =           TCON^3;
    sbit    IT1         =           TCON^2;
    sbit    IE0         =           TCON^1;
    sbit    IT0         =           TCON^0;

sfr         TMOD        =           0x89;
sfr         TL0         =           0x8A;
sfr         TL1         =           0x8B;
sfr         TH0         =           0x8C;
sfr         TH1         =           0x8D;
sfr         AUXR        =           0x8E;

sfr         P1          =           0x90;
    sbit    P10         =           P1^0;
    sbit    P11         =           P1^1;
    sbit    P12         =           P1^2;
    sbit    P13         =           P1^3;
    sbit    P14         =           P1^4;
    sbit    P15         =           P1^5;
    sbit    P16         =           P1^6;
    sbit    P17         =           P1^7;
    
    sbit    T2EX        =           P1^1;
    sbit    T2          =           P1^0;

sfr         SCON        =           0x98;
    sbit    SM0         =           SCON^7;
    sbit    SM1         =           SCON^6;
    sbit    SM2         =           SCON^5;
    sbit    REN         =           SCON^4;
    sbit    TB8         =           SCON^3;
    sbit    RB8         =           SCON^2;
    sbit    TI          =           SCON^1;
    sbit    RI          =           SCON^0;

sfr         SBUF        =           0x99;

sfr         P2          =           0xA0;
    sbit    P20         =           P2^0;
    sbit    P21         =           P2^1;
    sbit    P22         =           P2^2;
    sbit    P23         =           P2^3;
    sbit    P24         =           P2^4;
    sbit    P25         =           P2^5;
    sbit    P26         =           P2^6;
    sbit    P27         =           P2^7;
    
sfr         AUXR1       =           0xA2;

sfr         IE          =           0xA8;
    sbit    EA          =           IE^7;
    sbit    EC          =           IE^6;
    sbit    ET2         =           IE^5;
    sbit    ES          =           IE^4;
    sbit    ET1         =           IE^3;
    sbit    EX1         =           IE^2;
    sbit    ET0         =           IE^1;
    sbit    EX0         =           IE^0;
    
sfr         SADDR       =           0xA9;

sfr         P3          =           0xB0;
    sbit    P30         =           P3^0;
    sbit    P31         =           P3^1;
    sbit    P32         =           P3^2;
    sbit    P33         =           P3^3;
    sbit    P34         =           P3^4;
    sbit    P35         =           P3^5;
    sbit    P36         =           P3^6;
    sbit    P37         =           P3^7;

    sbit    RD          =           P3^7;
    sbit    WR          =           P3^6;
    sbit    T1          =           P3^5;
    sbit    T0          =           P3^4;
    sbit    INT1        =           P3^3;
    sbit    INT0        =           P3^2;
    sbit    TXD         =           P3^1;
    sbit    RXD         =           P3^0;

sfr         IPH         =           0xB7;
sfr         IP          =           0xB8;
    sbit    PT2         =           IP^5;
    sbit    PS          =           IP^4;
    sbit    PT1         =           IP^3;
    sbit    PX1         =           IP^2;
    sbit    PT0         =           IP^1;
    sbit    PX0         =           IP^0;

sfr         SADEN       =           0xB9;
    
sfr         XICON       =           0xC0;
    sbit    PX3         =           XICON^7;
    sbit    EX3         =           XICON^6;
    sbit    IE3         =           XICON^5;
    sbit    IT3         =           XICON^4;
    sbit    PX2         =           XICON^3;
    sbit    EX2         =           XICON^2;
    sbit    IE2         =           XICON^1;
    sbit    IT2         =           XICON^0;

sfr         T2CON       =           0xC8;
    sbit    TF2         =           T2CON^7;
    sbit    EXF2        =           T2CON^6;
    sbit    RCLK        =           T2CON^5;
    sbit    TCLK        =           T2CON^4;
    sbit    EXEN2       =           T2CON^3;
    sbit    TR2         =           T2CON^2;
    sbit    C_T2        =           T2CON^1;
    sbit    CP_RL2      =           T2CON^0;
    
sfr         T2MOD       =           0xC9;
sfr         RCAP2L      =           0xCA;
sfr         RCAP2H      =           0xCB;
sfr         TL2         =           0xCC;
sfr         TH2         =           0xCD;

sfr         PSW         =           0xD0;
    sbit    CY          =           PSW^7;
    sbit    AC          =           PSW^6;
    sbit    F0          =           PSW^5;
    sbit    RS1         =           PSW^4;
    sbit    RS0         =           PSW^3;
    sbit    OV          =           PSW^2;
    sbit    F1          =           PSW^1;
    sbit    P           =           PSW^0;

sfr         ACC         =           0xE0;

sfr         WDT_CONTR   =           0xE1;
sfr         ISP_DATA    =           0xE2;
sfr         ISP_ADDRH   =           0xE3;
sfr         ISP_ADDRL   =           0xE4;
sfr         ISP_CMD     =           0xE5;
sfr         ISP_TRIG    =           0xE6;
sfr         ISP_CONTR   =           0xE7;

sfr         P4          =           0xE8;
    sbit    P40         =           P4^0;
    sbit    P41         =           P4^1;
    sbit    P42         =           P4^2;
    sbit    P43         =           P4^3;
    sbit    P44         =           P4^4;
    sbit    P45         =           P4^5;
    sbit    P46         =           P4^6;
    sbit    P47         =           P4^7;

sfr         B           =           0xF0;

/

#endif

代码也提示了,不需要再添加regx51.h 头文件了。

最后还有一个 delay.h 头文件,需要同时在工程中新建一个 delay.h 和一个 delay.c,内容如下:

/********************************************************************
 * File: delay.h
 * Description: Time delay function based on 11.0592MHz crystal
 * oscillator.
 * crystal oscillator.
 * Version: 1.0
 * Date: 2023-07-17
 * Author: zhengxinyu13@gmail.com
 * ---------- Revision History ----------
 * <version> <date> <author> <desc>
 * 
 ********************************************************************/

#ifndef __DELAY_H__
#define __DELAY_H__

#include "main.h"
#include "intrins.h"

void delay_ms(uint16_t xms);
void delay_1s(void);

#endif // __DELAY_H__
 
/********************************************************************
 * File: delay.h
 * Description: Delay function library based on 11.0592MHz
 * crystal oscillator.
 * Version: 1.0
 * Date: 2023-07-17
 * Author: zhengxinyu13@gmail.com
 * ---------- Revision History ----------
 * <version> <date> <author> <desc>
 * 
 ********************************************************************/

#include "delay.h"

/**
 * @brief Delay function in milliseconds.
 * @param Enter the delay time in milliseconds.
 */
void delay_ms(uint16_t xms)
{
    uint16_t i,j;
    for (i = 0; i < xms; i++)
        for (j = 0; j < 112; j++);
}

/**
 * @brief Delay by one second.
 */
void delay_1s(void)
{
    uint8_t i, j, k;

    _nop_();
    i = 8;
    j = 1;
    k = 243;
    do {
        do {
            while (--k);
        } while (--j);
    } while (--i);
}

这里特殊说明一下,这个延时函数的文件不是必要的,只是延时函数在 C51 的开发过程中太常见了,所以加上去方便后面的开发。

[!NOTE]

实际项目的单片机开发不会用在这种软件延时,太占用 CPU 了,通常是用定时中断计时,考虑到 C51 的资源太匮乏,在学习开发阶段,可以使用软件延时。

4. 编译配置

最后需要配置编译,否则编译后也不会生成 .hex 文件,在菜单栏中找打类似魔术棒一样的图标并点击。

在这里插入图片描述

这里建议把晶振频率设置成实际开发的频率,一般都是 11.0592MHz。

在这里插入图片描述

然后点击选项卡 Output,把 Create HEX File 勾上,Name of Executable 是编译后的 .hex 文件的文件名,我习惯使用 build。最后点击 OK 完成配置。

在这里插入图片描述

点击编译试一下,如果在下面的 Bulid Output 中出现 creating hex file from ".\Objects\build"... 的字样,就表示编译通过,并生成了 .hex 文件。有两个警告是因为 delay.c 中写了两个延时函数没有调用导致,知道原因可以忽略。

在这里插入图片描述

5. 其他

考虑到很多英文水平不好的同学写英文注释比较难受,可以使用中文注释,建议修改成 UTF-8。先在菜单栏找到小扳手的图标并打开,在 Encoding 中选择 Encode in UTF-8 without signature,不建议选择 GB2312 或者 BIG5,因为有些字符无法显示。

在这里插入图片描述

如果有同学对我的 Keil 主题比较感兴趣的话,我可以单独出一篇博客细说一下。

二、C51 的编码规范

关于编码规范,我基本都有比较统一的标准,可以直接参考我的博客《关于我个人的编码规范(C/C++)》,这里只补充一点,这规范中,我提到要将 tab 键设置成 4 个空格,统一用 tab 键缩进,这里教大家怎么把 Keil 的 tab 设置成 4 个空格。

按图设置即可。

在这里插入图片描述


  1. 个人感觉郭天祥老师有一定责任,当年他培养出新世纪以来第一批嵌入式工程师,他的十天学会 C51 的课程以及那本新概念的书功不可没,但是其课程和书的代码风格都很乱,这也可能是后来很多单片机工程师代码风格很差的一个原因。 ↩︎

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/626729.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Kubernetes——CNI网络组件

目录 一、Kubernetes三种接口 二、Kubernetes三种网络 三、VLAN与VXLAN 1.VLAN 2.VXLAN 3.区别 3.1作用不同 3.2vxlan支持更多的二层网络 3.3已有的网络路径利用效率更高 3.4防止物理交换机Mac表耗尽 3.5相对VLAN技术&#xff0c;VXLAN技术具有以下优势 四、CNI网…

设计模式-动态代理

目录 定义 代理模式的优缺点 优点 缺点 应用场景 静态代理 动态代理 相关资料 定义 代理模式&#xff08;Proxy Pattern&#xff09;是一种结构型设计模式&#xff0c;它的概念很简单&#xff0c;它通过创建一个代理对象来控制对原始对象的访问。代理模式主要涉及两个…

分布式搜索-elaticsearch基础 概念

什么是elaticsearch: 倒排索引&#xff1a;就是将要查询的内容分成一个个词条&#xff0c;在将词条文档id存入&#xff0c;词条是唯一的。 文档词条总结: mysql和Elasticsearch概念对比: 架构: 基本概念总结:

uniapp 实现下拉刷新 下滑更新

效果图 在app或者小程序中向下滑动 会出现刷新数据 ,而上拉到底 需要更新数据 功能实现 主要俩种方式 依赖生命周期 在page.json中开启 page.json "style" : {"navigationBarTitleText" : "小小练习","backgroundTextStyle": &qu…

Transformer模型详解05-Decoder 结构

文章目录 简介结构原理第一个 Multi-Head Attention第二个 Multi-Head AttentionSoftmax 预测输出单词 简介 Transformer 模型由编码器&#xff08;Encoder&#xff09;和解码器&#xff08;Decoder&#xff09;两部分组成。这里我会着重描述解码器的结构以及在预训练、输入输…

StNet: Local and Global Spatial-Temporal Modeling for Action Recognition 论文阅读

StNet: Local and Global Spatial-Temporal Modeling for Action Recognition 论文阅读 Abstract1 Introduction2 Related Work3 Proposed Approach4 Experiments5 Conclusion 文章信息&#xff1a; 原文链接&#xff1a;https://ojs.aaai.org/index.php/AAAI/article/view/4…

期权(1):基本概念,权利金,定金,买方,卖方,零和游戏,对赌协议

期权是合约&#xff0c;权利金就是定金&#xff01; 合约到期时 买方可以选择行权&#xff0c;也可以选择不行权。代价就是定金损失。因此亏损封顶&#xff0c;但盈利无限。卖方赚的就是买方的定金&#xff0c;盈利封顶&#xff0c;但亏损无限。 从这里&#xff0c;我们看出…

短视频拍摄+直播间搭建视觉艺术实战课:手把手场景演绎 从0-1短视频-8节课

抖音短视频和直播间你是否遇到这些问题? 短视频是用手机拍还是相机拍?画面怎么拍都没有质感 短视频产量低&#xff0c;拍的素材可用率低 看到别人用手机就能把短视频拍好自己却无从下手 明明已经打了好几盏灯了,但是画面还是比较暗 直播软件参数不会设置&#xff0c;电脑…

【Python探索之旅】列表

目录 特点 入门 访问元素 新增元素 修改元素 插入元素 删除元素 完结撒花 前言 在Python中&#xff0c;列表(List)是最常用的数据结构之一&#xff0c;类似于其他语言&#xff0c;如Java&#xff0c;与其不同啊Python中不需要声明数据类型。它提供了一种灵活且高效的方式…

MySQL创建索引报错 Specified key was too long;max key length is 1000 bytes.

MySQL对创建索引的大小有限制&#xff0c;一般索引键最大长度总和不能超过1000个字节。 问题描述 MySQL创建索引时报错 Specified key was too long;max key length is 1000 bytes. 解决办法 (1) 修改存储引擎 InnoDB的索引字段长度限制大于MyISAM&#xff0c;可以尝试改成…

ansible利用playbook 部署lamp架构

搭建参考&#xff1a;ansible批量运维管理-CSDN博客 定义ansible主机清单 [rootansible-server ~]# vim /etc/hosts 192.168.200.129 host01 192.168.200.130 host02 [rootansible-server ~]# vim /etc/ansible/hosts [webserver] host01 host02 在ansible端编写index.html…

【windows小知识#1】ISO镜像,OEM、Retail这些到底是什么意思

汇总一下每个版本windows会衍生哪些镜像出来&#xff0c;以windows7为例 这些文件名代表的是不同版本和不同语言的Windows 7操作系统的安装光盘映像&#xff08;ISO文件&#xff09;。这些文件主要区分为以下几个方面&#xff1a; 语言&#xff1a;这些文件都是中文版&#x…

平地惊雷,GPT-4o 凌晨震撼发布

GPT-4o 今日凌晨&#xff0c;OpenAI 2024 年春季发布会召开&#xff0c;OpenAI 通过短短 28 分钟的发布会&#xff0c;发布了「再次震惊世界」的 GPT-4o&#xff0c;其中 o 是指 omni&#xff08;全能&#xff09;的意思。 一款「全新交互&#xff08;支持 文本/音频/视频 组合…

【AI学习】聊两句昨夜OpenAI的GPT-4o

蹭个热点&#xff0c;聊两句昨夜的大事件——OpenAI发布GPT-4o&#xff0c;我看到和想到的一点东西。 首先是端到端方法&#xff0c;前面关于深度学习的文章&#xff0c;对端到端的重要性做了一些学习&#xff0c;对端到端这个概念有了一些理解。正如Richard Sutton在《苦涩的…

直播预约丨《袋鼠云大数据实操指南》No.2:实时开发,如何成为数据智能化的有效驱动力

近年来&#xff0c;新质生产力、数据要素及数据资产入表等新兴概念犹如一股强劲的浪潮&#xff0c;持续冲击并革新着企业数字化转型的观念视野&#xff0c;昭示着一个以数据为核心驱动力的新时代正稳步启幕。 面对这些引领经济转型的新兴概念&#xff0c;为了更好地服务于客户…

C语言中的混合运算

1 混合运算 类型强制转换场景 整型数进行除法运算时&#xff0c;如果运算结果为小数&#xff0c;那么存储浮点数时一定要进行强制转换。例子&#xff1a; #include <stdio.h> //运算强制转换 int main(void) {int i5;//整型float ji/2;//这里做的是整型运算&#xff0…

【Linux取经路】进程通信之匿名管道

文章目录 一、进程间通信介绍1.1 进程间通信是什么&#xff1f;1.2 进程间通信的目的1.3 进程通信该如何实现 二、管道2.1 匿名管道2.1.1 站在文件描述符角度深入理解管道2.1.2 接口使用2.1.3 PIPE_BUFFER 和 Pipe capacity2.1.4 管道中的四种情况2.1.5 管道特征总结 2.2 匿名管…

PDF文件转换为CAD的方法

有时候我们收到一个PDF格式的设计图纸&#xff0c;但还需要进行编辑或修改时&#xff0c;就必须先将PDF文件转换回CAD格式。分享两个将PDF转换回CAD的方法&#xff0c;一个用到在线网站&#xff0c;一个用到PC软件&#xff0c;大家根据情况选择就可以了。 ☞在线CAD网站转换 …

STM32 CANFD 基础知识留档

讲得比较细的文章但可能有问题自行判定 附1 附2 前言 CAN2.0 协议中数据段波特率和仲裁段波特率默认是一致&#xff0c;因此只需要关注传输波特率即可 CANFD 协议是向下兼容 CAN2.0 的数据通讯&#xff0c;因此实际使用中需要配置 STM32H7 系列支持的标准是 Compliant with …

vue-cropper裁剪图片 vue

效果图 1.配置环境 npm install vue-cropper 2.代码 <template><div class"cropper-content"><div class"cropper-box"><div class"cropper"><vue-cropper ref"cropper" :img"option.img" :…