【GD32F427开发板试用】位带操作实现多线程下的跑马灯

news2024/9/24 19:22:30

本篇文章来自极术社区与兆易创新组织的GD32F427开发板评测活动,更多开发板试用活动请关注极术社区网站。作者:SmallWhite

一、位带操作

作用:对某一位或者几个连续的位进行操作

前言

我们在使用GD32等单片机时使用到的固件库编程,很经常会遇到位带操作,固件库对外设寄存器的每个关键bit都做了定义,例如宏定义中的:

写1:用1左移n位后和具体位进行|=的运算得到
写0:用1左移n位后取反得到第n位的0值然后和具体位进行&=的运算得到

/* GPIO_OCTL */
#define GPIO_OCTL_OCTL0            BIT(0)               
#define GPIO_OCTL_OCTL1            BIT(1)

例如上述代码中的端口输出控制寄存器(GPIOx_OCTL),和待会还要用到的端口输入状态寄存器(GPIOx_ISTA),想要实现对GPIO的某一位(某一pin)操作的话,需要知道这两个寄存器的地址
1.端口输入状态寄存器(GPIOx_ISTAT, x=A…I)
地址偏移:0x10
复位值:0x0000 XXXX
2.端口输出控制寄存器(GPIOx_OCTL, x=A…I)
地址偏移:0x14
复位值:0x0000 0000

所以说每个端口x的输入状态以及输出控制寄存器的地址=端口x基地址+寄存器的偏移地址:

#define output_offset 0x14
#define input_offset  0x10

//IO口地址映射
#define GPIOA_ODR_Addr    (GPIOA+output_offset) //0X40020000U+0x0U+output_offset
#define GPIOB_ODR_Addr    (GPIOB+output_offset) //0X40020000U+0x00000400U+output_offset
#define GPIOC_ODR_Addr    (GPIOC+output_offset) //0X40020000U+0x00000800U+output_offset
#define GPIOD_ODR_Addr    (GPIOD+output_offset) 
#define GPIOE_ODR_Addr    (GPIOE+output_offset) 
   
#define GPIOA_IDR_Addr    (GPIOA+input_offset) 
#define GPIOB_IDR_Addr    (GPIOB+input_offset)  
#define GPIOC_IDR_Addr    (GPIOC+input_offset)
#define GPIOD_IDR_Addr    (GPIOD+input_offset) 
#define GPIOE_IDR_Addr    (GPIOE+input_offset)

二、实现位带操作的前提条件

1.支持位带操作的两个内存区的范围是:
0x2000_0000‐0x200F_FFFF(SRAM区中的最低1MB)
0x4000_0000‐0x400F_FFFF(片上外设区中的最低1MB)
而GPIOA~GPIOE的地址刚好在以上范围内(0x4002 0000~0x4002 1000)

2.查阅GD32的数据手册说明:

3.对于片上外设位带区的某个bit,我们假设记它所在字节地址为A,位序号为n,则该bit在别名区的地址为:
Addr=0x42000000+(A-0x40000000)_32+4_n

4.回到代码中实现:
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))
整体宏定义代码如下:

//IO口操作宏定义
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2)) 
#define MEM_ADDR(addr)  *((volatile unsigned long  *)(addr)) 
#define BIT_ADDR(addr, bitnum)   MEM_ADDR(BITBAND(addr, bitnum)) 

#define output_offset 0x14
#define input_offset  0x10

//IO口地址映射
#define GPIOA_ODR_Addr    (GPIOA+output_offset) //0X40020000U+0x0U+output_offset
#define GPIOB_ODR_Addr    (GPIOB+output_offset) //0X40020000U+0x00000400U+output_offset
#define GPIOC_ODR_Addr    (GPIOC+output_offset) //0X40020000U+0x00000800U+output_offset
#define GPIOD_ODR_Addr    (GPIOD+output_offset) 
#define GPIOE_ODR_Addr    (GPIOE+output_offset) 
   
#define GPIOA_IDR_Addr    (GPIOA+input_offset) 
#define GPIOB_IDR_Addr    (GPIOB+input_offset)  
#define GPIOC_IDR_Addr    (GPIOC+input_offset)
#define GPIOD_IDR_Addr    (GPIOD+input_offset) 
#define GPIOE_IDR_Addr    (GPIOE+input_offset)

//IO口操作,只对单一的IO口!
//确保n的值小于16!
#define PAout(n)   BIT_ADDR(GPIOA_ODR_Addr,n)  //输出 
#define PAin(n)    BIT_ADDR(GPIOA_IDR_Addr,n)  //输入 

#define PBout(n)   BIT_ADDR(GPIOB_ODR_Addr,n)  //输出 
#define PBin(n)    BIT_ADDR(GPIOB_IDR_Addr,n)  //输入 

#define PCout(n)   BIT_ADDR(GPIOC_ODR_Addr,n)  //输出 
#define PCin(n)    BIT_ADDR(GPIOC_IDR_Addr,n)  //输入 

#define PDout(n)   BIT_ADDR(GPIOD_ODR_Addr,n)  //输出 
#define PDin(n)    BIT_ADDR(GPIOD_IDR_Addr,n)  //输入 

#define PEout(n)   BIT_ADDR(GPIOE_ODR_Addr,n)  //输出 
#define PEin(n)    BIT_ADDR(GPIOE_IDR_Addr,n)  //输入
void Led_Flash_Task(void *p_arg)
{
    OS_ERR err;
    while(1)
    {
        running_led_out=!running_led_out;
        OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_PERIODIC,&err);//延时1s
    }
}

5.现在跑个UCOS多线程下的跑马灯看看:

可以看到正常运行串口发送线程和跑马灯线程,UCOS部分的移植也是看网上的,具体步骤还没时间去完全理清思路,现在就是能跑的状态,目前也是发的第一篇文章,如有错误请多多指教!

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

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

相关文章

int 和 Integer 有什么区别?为什么要有包装类?

基本数据类型 在 Java 中&#xff0c;一共有 8 种基本类型&#xff08;primitive type&#xff09;&#xff0c;其中有 4 种整型、2 种浮点类型、1 种用于表示 Unicode 编码的字符类型 char 和 1 种用于表示真假值的 boolean 类型。 4 种整型&#xff1a;int、short、long、by…

Godot实现蝴蝶飞舞Shader

前言 我一直在探索在游戏UI中实现特效的方法&#xff0c;如LOL&#xff0c;王者荣耀那种华丽的UI特效。 经过总结有一些方法 1、AE做特效渲染成序列帧供游戏引擎播放 优点&#xff1a;节省资源&#xff0c;适合定制特殊需求 缺点&#xff1a;太大占地方&#xff0c;不好修改…

【H5小游戏】-使用js复刻经典小游戏【接鸡蛋】,快来帮助鸡妈妈找回蛋宝宝吧

接鸡蛋游戏需求&#x1f447;核心玩法&#x1f447;&#x1f447;界面原型&#x1f447;&#x1f447;成品演示&#x1f447;1.游戏演示2.暂停演示游戏开发1.游戏素材准备2.代码实现1.创建index.html页面复刻经典小游戏【接鸡蛋】&#xff0c;快来帮助鸡妈妈找回它的蛋宝宝吧 …

用友BIP与旺店通·企业奇门对接集成采购订单列表查询=>创建采购单(采购订单=>采购单)

用友BIP与旺店通企业奇门对接集成采购订单列表查询>创建采购单(采购订单>采购单-p)来源系统:用友BIP用友BIP助力行业龙头企业、产业链核心企业以及平台型企业建设产业互联网运营平台&#xff0c;通过运营、管理、协同配置和共享资源&#xff0c;实现产业链上下游连接与协…

基于 CartPole-v0 环境的强化学习算法实现(附完整代码)

1.1 CartPole-v0Cart Pole 在 OpenAI 的 gym 模拟器里面是相对比较简单的一个游戏。游戏里面有一个小车&#xff0c;上有 一根杆子。小车需要左右移动来保持杆子竖直。如果杆子倾斜的角度大于 15&#xff0c;那么游戏结束。小车也不 能移动出一个范围&#xff08;中间到两边各 …

03 利用栈进行中缀表达式计算

运算符优先级 ​​​​ 栈内运算符加减乘除取模优先级比栈外优先级大1&#xff0c;例如当23-5时我们往往从左到右计算&#xff0c;即先算再算-&#xff0c;使用中缀表达式两个栈计算就是栈外-优先级低于栈顶&#xff0c;故会弹出运算符和两个操作数进行计算。 中缀表达式计算…

Redis应用技术(3)List和Set在Feed流中的选择

在数据推送的时候,我们使用Feed流 Feed流有三种推送数据的方式(以微博订阅为例) 1.推模式(Push) 将数据在发出后直接推到每个收件箱中.这样会造成发送方的内存占用很大 2.拉模式 用户每次登录后主动的将数据从收件箱中拉去到,会造成用户的负载增加(如果关注的人很多,甚至会导…

SpringCloud——config远程连接github 踩坑

说明 我们现在使用spring cloud config 远程连接github会存在网络跟不上问题&#xff0c;以及本地git密钥问题。 1.github更改了密钥策略原来生成的rsa会导致报错&#xff0c;需要使用命令重新生成ed25519密钥2.配置需要按照上述配置 force-pull: true #这个参数不加可能会有…

Linux系统的启动与关闭

✅作者简介&#xff1a;热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏&#xff1a;Java案例分…

vue-循环引用感想

vue-循环引用感想开场-什么是循环引用探讨-怎么用后话如果我们要在主组件中传方法到子组件呢普通的porps传参依赖注入开场-什么是循环引用 刚开始看着这个官方文档上的循环引用十分的不解&#xff0c;意思是什么呢&#xff1f;看着官网的意思&#xff0c;大概举了个文件管理器…

Exceeded limit on max bytes to buffer : 262144

springboot版本 2.7.3springcloud版本 2021.0.3POST请求的body是1M多&#xff0c;请求网关提示报错。org.springframework.core.io.buffer.DataBufferLimitException: Exceeded limit on max bytes to buffer : 262144at org.springframework.core.io.buffer.LimitedDataBuffer…

使用 Burpsuite 测试的常用操作(一)

大家好啊&#xff0c;我是大田。今天分享一下 Burpsuite 在工作中常用操作&#xff0c;本文先说说其中两个操作。一、了解一下 Burpsuite 做什么1、Burpsuite 是一个黑客工具、安全测试工具、半自动化抓包、篡改信息。2、他能做&#xff1a;代理工具 Proxy 、爬虫 Spider、暴力…

python与excel

一、安装anaconda(阿里云镜像库) pip config list -v#pip在哪里寻找pip.conf文件 阿里云镜像&#xff1a; 1、安装完成&#xff0c;命令行输入&#xff1a;conda config生成.condarc文件&#xff08;运行期配置文件&#xff09; 2、如果原本的源中的源地址是 https&#xff0…

手撕Pytorch源码#2.Dataset类 part2

写在前面手撕Pytorch源码系列目的&#xff1a;通过手撕源码复习了解高级python语法熟悉对pytorch框架的掌握在每一类完成源码分析后&#xff0c;会与常规深度学习训练脚本进行对照本系列预计先手撕python层源码&#xff0c;再进一步手撕c源码版本信息python&#xff1a;3.6.13p…

十四.文件操作

目录 一.为什么使用文件 二.什么是文件 1.程序文件和数据文件 2.文件名 三.文件的打开和关闭 1.文件指针 2.fopen函数和fclose函数 四.文件的顺序读写 1.顺序读写函数一览表 2.主要输入输出函数介绍 &#xff08;1&#xff09;字符输出函数futc &#xff08;2&…

Python采集*瓣电影影评并实现可视化分析

前言 嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 又到了学Python时刻~ 环境使用: Python 3.8 解释器 Pycharm 编辑器 模块使用 import parsel >>> pip install parsel import requests >>> pip install requests import csv 安装python第三方…

LeetCode 1825 求出MK平均值【Set 队列】 HERODING的LeetCode之路

解题思路&#xff1a; 好久没更新力扣困难题的题解了&#xff0c;今天这道困难题有点意思&#xff0c;读罢题目一目了然&#xff0c;解题思路清晰明了&#xff0c;就是解题过程细节满满。这是一个数据流场景的问题&#xff0c;保留最后m个元素&#xff0c;但是要去除k个最大&am…

设计模式—工厂方法模式

工厂方法模式 文章目录工厂方法模式工厂方法模式是什么理解工厂方法模式代码实例运行截图工厂方法的优点工厂方法的不足工厂方法模式是什么 工厂方法模式属于创建型模式&#xff0c;也叫抽象构造模式&#xff0c; 工厂方法模式将工厂抽象化&#xff0c;并定义一个创建对象的接…

高级语言(C语言)、汇编语言、机器语言区别?编译器如何将高级语言编译成机器语言?

⾼级语⾔&#xff1a; 是相对于汇编语⾔⽽⾔的&#xff0c;是⾼度封装了的编程语⾔&#xff0c;与低级语⾔相对。它是以⼈类的⽇常语⾔为基础的⼀种编程语⾔&#xff0c;使⽤⼀般⼈易于接受的⽂字来表⽰&#xff08;例如汉字、不规则英⽂或其他外语&#xff09;&#xff0c;从…

(二十四)List系列集合

目录 前言: 一、List集合的特有方法 二、List集合的遍历方式有几种&#xff1f; 三、Arraylist集合底层原理 四、LinkedList的特点 前言: List集合包括JavaList接口以及List接口的所有实现类。List集合中的元素允许重复&#xff0c;各元素的顺序放是对象插入的顺序&#xff…