STC8H8K64U 学习笔记 - 位运算

STC8H8K64U 学习笔记 -位运算

  • 环境说明
    • 引脚说明
  • 位运算
    • 实例

环境说明

该内容仅针对我自己学习的开发板做的笔记,在实际开发中需要针对目标电路板的原理图进行针对性研究。

  • 芯片:STC8H8K64U
  • 烧录软件:stc-isp-v6.92G
  • 编码工具:天问

引脚说明

  • P0_0:蜂鸣器,按频率发音,1:高,0:低
  • P0_1:电动马达,0:停,1:动
  • P5_3:小蓝灯,0:灭,1:亮
  • P2_7:1 号 LED 灯,0:亮,1:灭
  • P2_6:2 号 LED 灯,0:亮,1:灭
  • P1_5:3 号 LED 灯,0:亮,1:灭
  • P1_4:4 号 LED 灯,0:亮,1:灭
  • P2_3:5 号 LED 灯,0:亮,1:灭
  • P2_2:6 号 LED 灯,0:亮,1:灭
  • P2_1:7 号 LED 灯,0:亮,1:灭
  • P2_0:8 号 LED 灯,0:亮,1:灭
  • P5_1:1 号按键,0:按下,1:弹起
  • P5_2:2 号按键,0:按下,1:弹起
  • P5_3:3 号按键,0:按下,1:弹起
  • P5_4:4 号按键,0:按下,1:弹起
  • P3_4:矩阵键盘第 1 行引脚
  • P3_5:矩阵键盘第 2 行引脚
  • P4_0:矩阵键盘第 3 行引脚
  • P4_1:矩阵键盘第 4 行引脚
  • P0_3:矩阵键盘第 1 列引脚
  • P0_6:矩阵键盘第 2 列引脚
  • P0_7:矩阵键盘第 3 列引脚
  • P1_7:矩阵键盘第 4 列引脚

位运算

对位运算进行小结

分析:设 n 为二进制数值的某一个位,在 8 位寄存器中,从高到低依次是:7654 3210

如果希望通过一个变量的二进制位置来作为按钮是否按下的标志位,

uint8 pressed = 0x00;
// 变量 pressed 的低四位表示按键的按下状态, 0 表示未按下, 1表示已按下
/  7  6  5  4     3  2  1  0          --> n 的取值
// 0  0  0  0     0  0  0  0          --> 二进制值
//               K4 K3 K2 K1          --> 针对按钮

若需要检测 n = 0 所在的位置的值是零还是壹,可以将 pressed 取反后与 0x01 进行与运算,如下所示

Let's say pressed is 0000 1010~pressed is 1111 01010x01 is 0000 0001 &The result is 0000 0001Let's say pressed is 0000 1011~pressed is 1111 01000x01 is 0000 0001 &The result is 0000 0000

若需要检测 n = 1 所在的位置的值是零还是壹,可以将 pressed 取反后与 0x02 进行与运算,如下所示

Let's say pressed is 0000 1000~pressed is 1111 01110x02 is 0000 0010 &The result is 0000 0010Let's say pressed is 0000 1011~pressed is 1111 01000x01 is 0000 0010 &The result is 0000 0000

类推:

  • 若检测第 1 位的值,即 n=0,将 pressed 取反后与 0x01 进行与运算
    • 若运算结果为 0x01, 则判定该位的值为 0
    • 若运算结果为 0x00, 则判定该位的值为 1
  • 若检测第 2 位的值,即 n=1,将 pressed 取反后与 0x02 进行与运算
    • 若运算结果为 0x02, 则判定该位的值为 0
    • 若运算结果为 0x00, 则判定该位的值为 1
  • 若检测第 3 位的值,即 n=2,将 pressed 取反后与 0x04 进行与运算
    • 若运算结果为 0x04, 则判定该位的值为 0
    • 若运算结果为 0x00, 则判定该位的值为 1
  • 若检测第 4 位的值,即 n=3,将 pressed 取反后与 0x08 进行与运算
    • 若运算结果为 0x08, 则判定该位的值为 0
    • 若运算结果为 0x00, 则判定该位的值为 1

不难发现,进行与运算的对象和 n 是有一定的关系的:

1<<0=0x1
1<<1=0x2
1<<2=0x4
1<<3=0x8
1<<4=0x10
1<<5=0x20
1<<6=0x40
1<<7=0x80

综上所述,总结如下:

设 n 为二进制数值的某一个位,在 8 位寄存器中,从高到低依次是:7654 3210

希望通过一个变量 pressed 的二进制位置来作为按钮是否按下的标志位,有如下结论:

若检测 n 位置的的值,将 pressed 取反后与 1<<n 进行& 运算

  • 若运算结果为 1<<n, 则判定该位的值为 0
  • 若运算结果为 0x00, 则判定该位的值为 1

实例

下面是一段来自天问编程工具中的代码。

针对的是开发板上的四个独立按键,它们对应的四个引脚分别是:P5_1、P5_2、P5_3 和 P5_4。

需求是,当按下按键后,向串口发送信息,报告此时按键的状态,并用一个标志位来记录其按下的状态。

#include <STC8HX.h>
uint32 sys_clk = 24000000;//设置PWM、定时器、串口、EEPROM频率参数
#include "lib/twen_board.h"
#include "lib/delay.h"
#include "lib/UART.h"
#include <stdio.h>#define K1 P5_1
#define K2 P5_2
#define K3 P5_3
#define K4 P5_4uint8 pressed = 0x00;
// 变量 pressed 的低四位表示按键的按下状态, 0 表示未按下, 1表示已按下
// 0  0  0  0     0  0  0  0
//               K4 K3 K2 K1void setup() {twen_board_init(); //天问51初始化uart_init(UART_1, UART1_RX_P30, UART1_TX_P31, 115200, TIM_1);//初始化串口P5M1&=~0x02; P5M0&=~0x02; // P5_1 设置为双向IOP5M1&=~0x04; P5M0&=~0x04; // P5_2 设置为双向IOP5M1&=~0x08; P5M0&=~0x08; // P5_3 设置为双向IOP5M1&=~0x80; P5M0&=~0x80; // P5_4 设置为双向IO
}void loop() {// 0000 0001if(K1 == 0 && ((0x01 & ~pressed) == 0x01)) {pressed|=0x01;uart_putstr(UART_1, "Key1 按下");} else if(K1 == 1 && ((0x01 &~ pressed) == 0x00)) {pressed&=~0x01;uart_putstr(UART_1, "Key1 弹起");}// 0000 0010if(K2 == 0 && ((0x02 & ~pressed) == 0x02)) {pressed|=0x02;uart_putstr(UART_1, "Key2 按下");} else if(K2 == 1 && ((0x02 &~ pressed) == 0x00)) {pressed&=~0x02;uart_putstr(UART_1, "Key2 弹起");}// 0000 0100if(K3 == 0 && ((0x04 & ~pressed) == 0x04)) {pressed|=0x04;uart_putstr(UART_1, "Key3 按下");} else if(K3 == 1 && ((0x04 &~ pressed) == 0x00)) {pressed&=~0x04;uart_putstr(UART_1, "Key3 弹起");}// 0000 1000if(K4 == 0 && ((0x08 & ~pressed) == 0x08)) {pressed|=0x08;uart_putstr(UART_1, "Key4 按下");} else if(K4 == 1 && ((0x08 &~ pressed) == 0x00)) {pressed&=~0x08;uart_putstr(UART_1, "Key4 弹起");}delay(200);
}void main(void) {setup();while(1){loop();}
}

运用下刚刚推导的结论,拿案例中的第三个按钮的判断语句来修改,如下所示:

if(K3 == 0 && (((1<<2) & ~pressed) == (1<<2))) {pressed|=(1<<2);uart_putstr(UART_1, "Key3 按下");
} else if(K3 == 1 && (((1<<2) &~ pressed) == 0x00)) {pressed&=~(1<<2);uart_putstr(UART_1, "Key3 弹起");
}

进一步改进,声明一个 8 位的变量 flag 来存储位移运算的结果。所以 loop 函数改造如下:


uint8 flag = 0x00;// 用来临时存储位移运算结果void loop() {// 0000 0001flag = 1<<0;if(K1 == 0 && ((flag & ~pressed) == flag)) {pressed|=flag;uart_putstr(UART_1, "Key1 按下");} else if(K1 == 1 && ((flag &~ pressed) == 0x00)) {pressed&=~flag;uart_putstr(UART_1, "Key1 弹起");}// 0000 0010flag = 1<<1;if(K2 == 0 && ((flag & ~pressed) == flag)) {pressed|=flag;uart_putstr(UART_1, "Key2 按下");} else if(K2 == 1 && ((flag &~ pressed) == 0x00)) {pressed&=~flag;uart_putstr(UART_1, "Key2 弹起");}// 0000 0100flag = 1<<2;if(K3 == 0 && ((flag & ~pressed) == flag)) {pressed|=flag;uart_putstr(UART_1, "Key3 按下");} else if(K3 == 1 && ((0x04 &~ pressed) == 0x00)) {pressed&=~flag;uart_putstr(UART_1, "Key3 弹起");}// 0000 1000flag = 1<<3;if(K4 == 0 && ((flag & ~pressed) == flag)) {pressed|=flag;uart_putstr(UART_1, "Key4 按下");} else if(K4 == 1 && ((flag &~ pressed) == 0x00)) {pressed&=~flag;uart_putstr(UART_1, "Key4 弹起");}delay(200);
}

其实,该案例如果能用循环将 四个 开关置入循环体来指代,会使得代码简化非常多。这个问题先搁置,等待后续学习。

最后,附加四个位运算的公式:

uint8 variable = 0x00;
uint8 n = 1;
// 将第 n 位置为 1
variable = variable | (1 << n);
// 将第 n 位置为 0
variable = variable & ~(1 << n);
// 将第 n 位置取反
variable = variable ^ (1 << n);
// 取出第 n 位的值
variable = (variable & (1 << n)) >> n;

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

蚂蚁退地,房价猛跌

蚂蚁退地&#xff0c;房价猛跌 2020年-2021年&#xff0c;蚂蚁集团先后拿下之江度假区钱塘江岸 XH1710-B1/B2-23 和 XH1708-02 地块。 一时间&#xff0c;"蚂蚁集团坐拥大量土地&#xff0c;欲打造全球总部"的消息传遍全国&#xff0c;之江板块房价连夜猛涨&#xff…

MATLAB近红外光谱分析技术应用

郁磊副教授&#xff0c;主要从事MATLAB编程、机器学习与数据挖掘、数据可视化和软件开发、生理系统建模与仿真、生物医学信号处理&#xff0c;具有丰富的实战应用经验&#xff0c;主编《MATLAB智能算法30个案例分析》、《MATLAB神经网络43个案例分析》相关著作。已发表多篇高水…

【Python语法实例】-12猜单词游戏

一、游戏背景与需求 猜单词游戏是一种经典的文字游戏,玩家需要通过提示的字母组合,猜出正确的单词。这个游戏不仅考验玩家的词汇量和推理能力,还能在娱乐中提升编程技能。我们的目标是创建一个简单易懂的猜单词游戏,让玩家在享受游戏乐趣的同时,也能感受到Python编程的实…

C# MES通信从入门到精通(8)——C#调用Webservice服务进行数据交互

前言 在上位机开发领域,使用webservice来访问客户的终端Mes系统是一项必备的技能,本文详细介绍了如何在c#中调用webservice服务,不仅介绍了使用添加服务引用直接调用webservice中的方法外还介绍了使用http的post方法调用webservice方法,过程详细且均为实战经验总结,对于初…

港口核心!达梦数据助力上港集团罗泾码头 I-TOS 系统升级改造

港口作为交通运输的枢纽和联通世界的窗口&#xff0c;肩负着带动区域经济发展及服务国际经贸的双重责任。在信息化浪潮推动下&#xff0c;自动化、数字化、智能化成为港口航运业转型发展的关键。 达梦数据积极推进港口数字化转型升级 &#xff0c;助力上港集团罗泾码头实现 I-T…

iOS Widget Custom Intent 去除邮件警告

当实现了可编辑小组件功能后,打包上传到app store,收到了苹果发来的邮件。 邮件详情 Hello, We noticed one or more issues with a recent delivery for the following app: • Version 4.0.5 • Build 116 Although delivery was successful, you may want to correct the …

青蛙过河(二分+前缀和)

题目描述 小青蛙住在一条河边&#xff0c;它想到河对岸的学校去学习。小青蛙打算经过河里的石头跳到对岸。 河里的石头排成了一条直线&#xff0c;小青蛙每次跳跃必须落在一块石头或者岸上。不过&#xff0c;每块石头有一个高度&#xff0c;每次小青蛙从一块石头起跳&#xf…

[问题记录] oracle问题汇总记录

plsql问题 1、oracle-initialization error could not locate OCI.dll 下载plsql客户端后&#xff0c;登录显示如图所示的错误 解决方法&#xff0c;点击下方链接&#xff0c;下载64位客户端 Instant Client for Microsoft Windows (x64) 64-bit (oracle.com) 2、显示中文乱…

深度学习训练中“num_workers”的作用

在深度学习训练中&#xff0c;num_workers是一个常见的参数&#xff0c;特别是在使用数据加载器&#xff08;如PyTorch的DataLoader&#xff09;时。num_workers指定了用于数据加载的子进程数量。这个参数对于提高数据加载的效率和加速训练过程至关重要。 num_workers的作用&a…

【资源分享】最全ChatGPT镜像免梯子

::: block-1 “时问桫椤”是一个致力于为本科生到研究生教育阶段提供帮助的不太正式的公众号。我们旨在在大家感到困惑、痛苦或面临困难时伸出援手。通过总结广大研究生的经验&#xff0c;帮助大家尽早适应研究生生活&#xff0c;尽快了解科研的本质。祝一切顺利&#xff01;—…

LeetCode 707. 设计链表(单链表、(非循环)双链表 模板)

你可以选择使用单链表或者双链表&#xff0c;设计并实现自己的链表。 单链表中的节点应该具备两个属性&#xff1a;val 和 next 。val 是当前节点的值&#xff0c;next 是指向下一个节点的指针/引用。 如果是双向链表&#xff0c;则还需要属性 prev 以指示链表中的上一个节点…

leetCode第十题 : 正则表达式匹配 动态规划【10/1000 python】

&#x1f464;作者介绍&#xff1a;10年大厂数据\经营分析经验&#xff0c;现任大厂数据部门负责人。 会一些的技术&#xff1a;数据分析、算法、SQL、大数据相关、python 作者专栏每日更新&#xff1a; LeetCode解锁1000题: 打怪升级之旅 LeetCode解锁1000题: 打怪升级之旅htt…

wordpress全站开发指南-面向开发者及深度用户(全中文实操)--初尝php

初尝php 打开你下载的wordpress文件夹&#xff0c;如果你用的xampp那它就在xampp安装的文件夹–htdocs文件夹–你可以新建一个test文件夹–新建一个test.php文件 <html><head><title>First attempt at PHP</title></head><body><?ph…

Spring注解开发和XML开发

目录 Spring简介发展史Spring Framework系统架构spring 核心概念IOC、IOC容器、Bean、DIIOC快速入门DI快速入门 IOCBean基础配置id与class属性name属性scope属性 Bean的实例化构造方法静态工厂实例工厂FactoryBean的使用&#xff08;工厂实例的简化&#xff09; Bean的生命周期…

【Qt】:常用控件(三:按钮类)

常用控件&#xff08;三&#xff09; 一.Push Button二.Radio Buttion三.Check Box 一.Push Button 使⽤ QPushButton 表⽰⼀个按钮.这也是当前我们最熟悉的⼀个控件了.QPushButton继承⾃QAbstractButton .这个类是⼀个抽象类.是其他按钮的⽗类. QAbstractButton 中,和 QPushBu…

微信小程序技术选型方案

在保持小程序原生优势的基础上,进一步提高了开发效率、代码质量和用户体验。 一、WePY Mobx Axios Vant Weapp 这个技术选型方案在保持小程序原生优势的基础上,进一步提高了开发效率、代码质量和用户体验,是一个较为全面和合理的选择。 基础框架选择: 使用微信官方提供的小…

Qt中出现中文乱码的原因以及解决方法

Qt专栏&#xff1a;http://t.csdnimg.cn/C2SDN 目录 1.引言 2.原因分析 3.源文件的编码格式修改方法 4.程序内部使用的默认编码格式修改方法 5.QString转std::string的方法 6.总结 1.引言 在编写Qt程序的时候&#xff0c;或多或少都可能遇到用QString时候&#xff0c;明明…

Docker 安装 | 部署MySQL 8.x 初始设置

1、准备工作 如果不想看前面的废话请直接右边目录跳到 运行容器 处 默认你已经有 docker 环境。 Windows 推荐 Docker Desktop &#xff08;下载地址&#xff09;并基于 WSL2 运行 Docker 环境 mac 推荐 Orbstack &#xff08;下载地址&#xff09;&#xff08;这个很节省资源&…

控制台RPG 游戏实现双缓冲无屏闪,玩家类,地图类

重整控制台RPG——双缓冲无屏闪以及第一个无中生有的地图类&#xff0c;玩家类_哔哩哔哩_bilibili 是鄙人解说鄙人的代码 #include <iostream> #include <string.h> #include <windows.h>#define KEY_DOWN(vKey) ((GetAsyncKeyState(vKey) & 0x8000) ?…

Stable diffusion 加载扩展列表报错解决方法

项目场景&#xff1a; 在使用Stable diffusion webui时&#xff0c;使用扩展列表出现错误 问题描述 点击loadfrom后&#xff0c;出现加载扩展列表报错 原因分析&#xff1a; 下载的扩展的时候&#xff0c;都是github 的url&#xff0c;需要科学上网&#xff0c;如果不能科学…