历史上的今天
返回首页

历史上的今天

今天是:2025年01月06日(星期一)

正在发生

2020年01月06日 | STM8学习笔记---union联合体的应用

2020-01-06 来源:eefocus

平时用单片机编写程序经常会遇到将一个16位数拆封为两个8位数,或者将将两个8位数组成一个16位数。如:

data = data_h * 256 + data_l;

data_h = data / 256;

data_l = data % 256;

对于8位单片来说计算乘法和除法比较耗时,也比较浪费单片机资源。除了将乘法和除法转换为 左移 或者 右移运算外,有没有其他好的方法来解决这个问题。无意间看到了联合体之后,发现用联合体来解决这个问题是再好不过的。


关于联合体的定义:

在进行某些算法的C语言编程的时候,需要使几种不同类型的变量存放到同一段内存单元中。也就是使用覆盖技术,几个变量互相覆盖。这种几个不同的变量共同占用一段内存的结构,在C语言中,被称作“共用体”类型结构,简称共用体,也叫联合体。


数据类型可以共用一段内存,那么就可以让两个8位数和一个16位数共用一段内存就行了。这样在用两个8位数组成16位数的时候,可以分别存储两个 8位数,读取的时候直接读取16位数就行。一个16位数分成两个8位数的时候,直接存储16位数,然后分别读取两个8位数就行。 那么先写一段代码测试测试:



union Value

{

    unsigned char c[2];

    unsigned int i;


};


union Value v;

unsigned char data_h;

unsigned char data_l;

unsigned int data;


void main( void )

{

    SysClkInit();

    while( 1 )

    {

        data_h = 0x01;

        data_l = 0x02;

        v.c[0] = data_h;

        v.c[1] = data_l;

        data = v.i;

        data += 1000;

        v.i = data;

        data_h = v.c[0];

        data_l = v.c[1];

        v.i = 0;

    }

}


在联合体中定义一个字符数组,数组长度为2位,再定义一整形变量,这样两个字符变量和一个整形变量共享16位地址。然后在程序中先给字符数组中两个变量赋值,然后读取整形变量,看看整形变量的值是不是由两个字符变量组成的。然后再给整形变量赋值,观察两个字符变量是不是整形变量拆分的。

在这里插入图片描述

可以看到给c[0]赋值0x01,给c[1]赋值0x02, i 的值就变成了 0x0102,说明c[0]的值为高8位,c[1]的值为低8位。符合预期效果。然后再给0x0102加上1000,赋给i,看看c[0]和c[1]值得变化。

在这里插入图片描述

可以看到0x0102加上1000后变成了0x04EA,将0x04EA值赋给i后,c[0]的值变为了0x04,为高8位,c[1]的值变为了0xEA为低8位。看来这样使用联合体是正确的。


但是在实际应用的时候,用数组区分高8位和低8位不直观,而且容易搞混。能不能将数组直接换成两个变量?那么很自然的会想到最常用的结构体。用结构体来替换这个数组。于是修改程序如下。


union Data

{

    struct

    {

        unsigned char h;

        unsigned char l;

    };

    unsigned int i;


};


union Data d;

unsigned char data_h;

unsigned char data_l;

unsigned int data;


void main( void )

{

    SysClkInit();

    while( 1 )

    {

        data_h = 0x03;

        data_l = 0x04;

        d.h = data_h;

        d.l = data_l;

        data = d.i;

        data += 1000;

        d.i = data;

        data_h = d.h;

        data_l = d.l;

        d.i = 0;

    }

}


测试结果如下:

在这里插入图片描述

给h赋值0x03,给l赋值0x04,i的值变为0x0304.

在这里插入图片描述

将data的值0x0304加上1000后变为0x06EC,在赋给i,于是h的值变为0x06,l的值变为0xEC,结果正常。


通过联合体和结构体的组合使用,可以很轻松的组合或者拆分16位数。在以后的应用中就可以不使用乘除法来处理数据拆分组合问题了。

推荐阅读

史海拾趣

DREMEL公司的发展小趣事

随着全球化的趋势日益明显,Dremio公司开始积极拓展国际市场。他们制定了详细的国际化战略,包括在海外市场设立分支机构、与当地企业建立合作关系、参加国际展会等。这些举措不仅提高了Dremio公司在国际市场的知名度,也为其带来了更多的商业机会。通过国际化战略的实施,Dremio公司的业务规模不断扩大,品牌影响力也日益增强。

请注意,以上故事均基于虚构,旨在展示一个类似Dremio公司在电子行业中的可能发展路径和故事。如有需要,请进一步核实相关事实和数据。

东晨(DC)公司的发展小趣事

在电子行业中,合作与竞争并存。东晨(DC)公司善于在合作中寻求共赢,与产业链上下游企业建立了紧密的合作关系。同时,公司也积极参与市场竞争,通过不断创新和优化产品,提高市场竞争力。在与国内外同行的竞争中,东晨(DC)公司始终保持着领先地位,赢得了市场的广泛认可。

Chauvin Arnoux公司的发展小趣事

到了1960年,Chauvin Arnoux推出了Monoc测试仪,这是一种带有旋转开关和统一测量刻度的测量仪器。Monoc测试仪以其简洁、直观的操作界面和精确的测量能力,迅速成为电工行业的首选测量工具。这一产品的普及,进一步巩固了Chauvin Arnoux在电气测量领域的领导地位。

Global Communications公司的发展小趣事
通过温度传感器检测环境温度,并将检测到的温度信号转换为电信号后,送入到专门的补偿电路中。补偿电路根据温度信号调整晶体振荡器的输出频率或相位,以达到补偿的目的。这种方法相对复杂,但可以实现更精确的补偿效果。
AVG [AVG Semiconductors(HITEK)]公司的发展小趣事

在电子行业的发展过程中,AVG也面临着各种挑战和危机。例如,随着全球贸易保护主义的抬头和原材料价格的波动,公司的生产成本不断上升;同时,新技术的不断涌现和市场竞争的加剧也给公司带来了不小的压力。然而,AVG始终保持着冷静和清醒的头脑,积极应对各种挑战和危机。公司通过优化生产流程、提高生产效率、加强成本控制等措施,降低了生产成本;同时,加大研发投入,推出具有竞争力的新产品,以应对市场竞争的挑战。这些举措使得AVG在困境中保持了稳健的发展态势。

Extech公司的发展小趣事

1994年,Extech公司推出了国内第一套基于“AutoCAD FOR WINDOWS”的XTMCAD软件,这一创新举措标志着公司在CAD领域迈出了坚实的步伐。XTMCAD软件凭借其先进的技术和易用性,迅速获得了市场的认可,并在同年荣获了国家教委科技进步一等奖。这一荣誉不仅是对Extech公司技术实力的肯定,也为公司未来的发展奠定了坚实的基础。

问答坊 | AI 解惑

FPGA防抖

大家做过FPGA防抖没 分享下…

查看全部问答>

GSM模块——实现远程控制的新锐

GSM模块——实现远程控制的新锐…

查看全部问答>

移植ax88796 网卡驱动到vivi时遇到的问题,望大虾们帮帮忙!!!

在网上下了一个有tftp功能的vivi,但是要自己添加ax88796网卡的驱动,现将uboot-1.2.0中对应的ne2000的驱动copy到vivi下面,编译通过后,当在板子上运行的时候就出错了,后来通过prink的信息追踪到了下面的函数: static void dp83902a_poll(void ...…

查看全部问答>

熟悉minicom的或者串口的请进》》

本人初学linux ,在输入minicom命令的时候出现了串口老是不能用: Device /dev/ttyS0 lock failed:Operation not permitted 的信息,在网上也看过其他的方法用ps auxf |grep minicom 命令,再kill进程的方法也试过了,但是ps auxf |grep minicom ...…

查看全部问答>

关于字符串指针的初始化

如果要初始化一个字符串有两种写法: 1:char *p = \"hello\"; 2:char *p; p = \"hello\"; 这两种写法有没有错的,是否有区别。 谭浩强c程序设计p238说是一样的,大家讨论一下吧 …

查看全部问答>

不知算不上stm32vet6Z的硬件BUG

USART3映射方式2(映射到PD8,PD9)时,要先开启AFIO功能,再初始化相关外设后,USART才有效。      以下代码是正确的:      u32 backRcc = RCC->APB2ENR & (RCC_APB2Periph_GPIOB  | ...…

查看全部问答>

CCS下调试EK-8962时出错得原因?

前几天我在调试EKK-8962时,IDE为CCS4.2.4,在debug时出现如下的错误:CORTEX_M3_0: Error connecting to the target: The target board you are attempting to connect to does not appear to be a Stellaris IDK and is not supported with thi ...…

查看全部问答>

mega16 DS3231供电问题。。。

请问,我的系统要求MEGA16必须用5V供电,DS3231在5V供电时走时不准确,如果用3.3V供电的话如何处理?…

查看全部问答>

zigbeez在智能家居中有成熟方案的公司有几家

我想搞一个智能家居系统,用zigbee技术,不知道这样的厂家多吗?做的好的有那几家?…

查看全部问答>