#define SW_MUX_GPIO1_IO03 *((volatile unsigned int *)0X020E0068)

#define SW_MUX_GPIO1_IO03 *((volatile unsigned int *)0X020E0068)

这段代码涉及到C语言的宏定义和指针转换操作,是在嵌入式系统中常见的技巧,用于访问硬件寄存器。

  1. #define: 这是C语言中的宏定义指令,是为一个特定的文本片段定义一个符号名称,以便在代码中使用。

  2. SW_MUX_GPIO1_IO03: 这是为寄存器地址定义的宏名称。每当在代码中使用 SW_MUX_GPIO1_IO03 时,预处理器将替换为 *((volatile unsigned int *)0X020E0068),从而实际上将访问特定寄存器的操作插入到代码中。

  3. *((volatile unsigned int *)0X020E0068): 这是一个复杂的表达式,将访问硬件寄存器的操作封装在内。逐步解释:

    • (volatile unsigned int *)0X020E0068: 这是将地址 0X020E0068 转换为指向 volatile unsigned int 类型的指针。在这里,volatile 关键字的作用是告诉编译器不要对指针引用的内容进行优化,因为寄存器内容可能会在程序执行过程中随时改变。

    • *((volatile unsigned int *)0X020E0068): 这是对上面转换的指针内容进行解引用操作。这意味着程序将读取或写入寄存器 0X020E0068 的内容。

综合起来,这个宏定义实际上是为了方便地访问寄存器地址 0X020E0068 处的内容,即 GPIO1_IO03 引脚的 IOMUX 相关寄存器。通过使用这个宏,可以在代码中简单地使用 SW_MUX_GPIO1_IO03 来读取或写入这个寄存器,而无需每次都编写完整的指针转换和解引用操作。

另一个例子:

例2:

/*
 * @description		: 读取指定点的颜色值
 * @param - x		: x轴坐标
 * @param - y		: y轴坐标
 * @return 			: 读取到的指定点的颜色值
 */
inline unsigned int lcd_readpoint(unsigned short x,unsigned short y)
{ 
	return *(unsigned int*)((unsigned int)tftlcd_dev.framebuffer + 
		   tftlcd_dev.pixsize * (tftlcd_dev.width * y + x));
}

函数体中:

*(unsigned int*)((unsigned int)tftlcd_dev.framebuffer + 
		   tftlcd_dev.pixsize * (tftlcd_dev.width * y + x));

这里使用 (unsigned int*) 强制类型转换的目的是将后面内容解释为一个地址,

然后*(unsigned int*)就是访问这个地址处的内容。

inline关键字:

这里使用inline关键字是为了提高程序的运行效率,因为这个函数的定义很小,而且可能会被频繁地调用。如果不使用inline关键字,那么每次调用这个函数都会产生一些额外的开销,比如保存和恢复寄存器,跳转和返回等。使用inline关键字可以让编译器将这个函数的代码直接替换到每个调用的地方,从而避免这些开销。但是,使用inline关键字也有一些缺点,比如可能会增加代码的大小,因为每个调用都会复制一份函数的代码。

volatile 关键字:

在C语言中,volatile 是一个关键字,用于告诉编译器不要对变量进行某些优化,因为变量的值可能在程序运行期间随时发生变化,而编译器默认会进行一些优化来提高代码的执行效率。

在嵌入式系统中,经常会与硬件相关的寄存器、外设以及并行处理等情况。这些情况下,变量的值可能会受到程序之外的因素影响,比如硬件状态的变化。而编译器为了提高代码执行效率,可能会对变量进行优化,认为变量的值不会改变,从而可能导致错误的行为。这就是为什么在处理这些特殊情况时,需要使用 volatile 关键字。

代码中,volatile 关键字被用于指示编译器,寄存器内容可能会在程序执行期间被外部因素(比如硬件操作)修改,因此编译器不应该对这个寄存器内容进行优化,以确保程序能够正确地与硬件交互。

在这个上下文中,volatile 关键字的作用是确保编译器不会在不考虑外部因素的情况下进行优化,而是每次都从寄存器地址读取或写入内容,以确保程序的行为和硬件的实际状态保持一致。

总结起来,volatile 关键字用于告诉编译器不要对变量进行优化,以确保变量的值能够及时地反映外部因素的变化,这在与硬件相关的代码中尤为重要。

附:例2代码的理解:

把LCD帧缓冲区想象成一个画布,上面有很多彩色的点,每个点就是一个像素。每个像素都有自己的坐标,比如(0,0)表示左上角的点,(tftlcd_dev.width-1, tftlcd_dev.height-1)表示右下角的点。每个像素也有自己的颜色,比如红色、绿色、蓝色等。颜色是由四个数字组成的,分别表示红色、绿色、蓝色和透明度的强度,范围是0到255。比如(255,0,0,255)表示纯红色,(0,255,0,255)表示纯绿色,(0,0,255,255)表示纯蓝色,(0,0,0,0)表示透明。

现在,如果你想知道某个点的颜色是什么,你就需要找到这个点在画布上的位置,然后读取它的颜色值。但是,画布并不是直接显示在屏幕上的,而是存储在内存中的一个区域,叫做帧缓冲区。帧缓冲区是由很多字节组成的,每个字节都有自己的地址,比如0x80000000表示第一个字节的地址,0x80000001表示第二个字节的地址,以此类推。帧缓冲区中的每个字节都存储了一个数字,范围是0到255。这些数字就是用来表示像素的颜色的。

那么问题来了,怎么把像素的坐标和颜色跟帧缓冲区中的地址和数字对应起来呢?这就需要用到一些公式和规则。首先,我们要知道每个像素占用多少个字节。这取决于像素的格式,也就是用多少位来表示一个像素的颜色。在这里,我们使用32位每像素的RGBA格式,也就是说每个像素占用4个字节,分别表示红色、绿色、蓝色和透明度的分量。所以tftlcd_dev.pixsize(LCD每个像素所占字节大小)就是4。

其次,我们要知道帧缓冲区中存储像素的顺序和方向。一般来说,帧缓冲区中存储像素是按照行优先顺序的,也就是说先存储第一行的所有像素,然后存储第二行的所有像素,以此类推。而且一般来说,帧缓冲区中存储像素是从左到右、从上到下的方向的,也就是说左上角的点对应第一个字节,右上角的点对应第tftlcd_dev.width * 4个字节(因为一行有tftlcd_dev.width个像素),左下角的点对应第(tftlcd_dev.height - 1) * tftlcd_dev.width * 4 + 1个字节(因为一共有tftlcd_dev.height行),右下角的点对应最后一个字节。

最后,我们要知道帧缓冲区中存储像素颜色分量的顺序和大小端模式。一般来说,在32位每像素的RGBA格式中,每个像素占用4个字节时,最低位(最右边)的字节表示红色分量(R),次低位(右数第二位)的字节表示绿色分量(G),次高位(左数第二位)的字节表示蓝色分量(B),最高位(最左边)的字节表示透明度分量(A)。而且一般来说,帧缓冲区中存储像素颜色分量是按照小端模式的,也就是说低位字节存储在低地址,高位字节存储在高地址。比如,如果一个像素的颜色是(255,0,0,255),也就是纯红色,那么它占用的4个字节的值分别是0xFF, 0x00, 0x00, 0xFF。如果这个像素对应的第一个字节的地址是0x80000000,那么它占用的4个字节的地址分别是0x80000000, 0x80000001, 0x80000002, 0x80000003。

有了这些公式和规则,我们就可以根据像素的坐标和颜色跟帧缓冲区中的地址和数字对应起来了。比如,如果我们想读取(100,200)这个点的颜色值,我们就需要先找到这个点在帧缓冲区中对应的第一个字节的地址。根据前面说的规则,这个地址等于帧缓冲区的首地址加上这个点在帧缓冲区中的偏移量。偏移量等于这个点所在行数乘以每行占用的字节数加上这个点所在列数乘以每个像素占用的字节数。所以这个地址等于tftlcd_dev.framebuffer + (200 * tftlcd_dev.width + 100) * tftlcd_dev.pixsize。然后我们就可以从这个地址开始读取4个字节,得到这个点的颜色值。注意,因为帧缓冲区中存储像素颜色分量是按照小端模式的,所以我们读取到的4个字节要按照反序拼接成一个32位的无符号整数,才能得到正确的颜色值。所以这个颜色值等于*(unsigned int*)((unsigned int)tftlcd_dev.framebuffer + (200 * tftlcd_dev.width + 100) * tftlcd_dev.pixsize)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值