历史上的今天
返回首页

历史上的今天

今天是:2024年11月04日(星期一)

正在发生

2021年11月04日 | 指针的第五大好处,指针在众多数组中的中转站作用

2021-11-04 来源:eefocus

一、使用proteus绘制简单的电路图,用于后续仿真

二、编写程序


/********************************************************************************************************************

---- @Project: Pointer

---- @File: main.c

---- @Edit: ZHQ

---- @Version: V1.0

---- @CreationTime: 20200809

---- @ModifiedTime: 20200809

---- @Description:

---- 波特率是:9600 。

---- 通讯协议:EB 00 55  XX   

---- 通过上位机来调用下位机对应的数组数据 。

---- 通过电脑串口调试助手,往单片机发送EB 00 55 XX 指令,其中EB 00 55是数据头,XX的取值范围是0x01 至 0x05,每个不同的值代表调用下位机不同的数组数据。0x01调用第1组数据,0x02调用第2组数据,0x05调用第5组数据。

---- 第1组:11 12 13 14 15

---- 第2组:21 22 23 24 25

---- 第3组:31 32 33 34 35

---- 第4组:41 42 43 44 45 

---- 第5组:51 52 53 54 55

----

---- 下位机返回21个数据,前面5个是第1种不带指针函数返回的数据。中间5个是第2种不带指针函数返回的数据。最后5个是第3种带指针函数返回的数据。期间2组EE EE EE是各函数返回的数据分割线,为了方便观察,没实际意义。

---- 比如电脑发送:EB 00 55 02

---- 单片机就返回:21 22 23 24 25 EE EE EE 21 22 23 24 25 EE EE EE 21 22 23 24 25 

---- 单片机:AT89C52

********************************************************************************************************************/

#include "reg52.h"

/*——————宏定义——————*/

#define FOSC 11059200L

#define BAUD 9600

#define T1MS (65536-FOSC/12/500)   /*0.5ms timer calculation method in 12Tmode*/

 

#define const_array_size  5  /* 参与排序的数组大小 */

 

#define const_voice_short 19 /*蜂鸣器短叫的持续时间*/

#define const_rc_size 10 /*接收串口中断数据的缓冲区数组大小*/

 

#define const_receive_time 5 /*如果超过这个时间没有串口数据过来,就认为一串数据已经全部接收完,这个时间根据实际情况来调整大小*/

 

/*——————变量函数定义及声明——————*/

/*蜂鸣器的驱动IO口*/

sbit BEEP = P2^7;

/*LED*/

sbit LED = P3^5;

 

unsigned int uiSendCnt = 0; /*用来识别串口是否接收完一串数据的计时器*/

unsigned char ucSendLock = 1; /*串口服务程序的自锁变量,每次接收完一串数据只处理一次*/

unsigned int uiRcregTotal = 0; /*代表当前缓冲区已经接收了多少个数据*/

unsigned char ucRcregBuf[const_rc_size]; /*接收串口中断数据的缓冲区数组*/

unsigned int uiRcMoveIndex = 0; /*用来解析数据协议的中间变量*/

 

unsigned int uiVoiceCnt = 0; /*蜂鸣器鸣叫的持续时间计数器*/

 

const unsigned char array_0x01[] = {0x11, 0x12, 0x13, 0x14, 0x15};

const unsigned char array_0x02[] = {0x21, 0x22, 0x23, 0x24, 0x25};

const unsigned char array_0x03[] = {0x31, 0x32, 0x33, 0x34, 0x35};

const unsigned char array_0x04[] = {0x41, 0x42, 0x43, 0x44, 0x45};

const unsigned char array_0x05[] = {0x51, 0x52, 0x53, 0x54, 0x55};

 

/**

* @brief  定时器0初始化函数

* @param  无

* @retval 初始化T0

**/

void Init_T0(void)

{

TMOD = 0x01;                    /*set timer0 as mode1 (16-bit)*/

TL0 = T1MS;                     /*initial timer0 low byte*/

TH0 = T1MS >> 8;                /*initial timer0 high byte*/

}

 

/**

* @brief  串口初始化函数

* @param  无

* @retval 初始化T0

**/

void Init_USART(void)

{

SCON = 0x50;

TMOD = 0x21;                    

TH1=TL1=-(FOSC/12/32/BAUD);

}

 

/**

* @brief  外围初始化函数

* @param  无

* @retval 初始化外围

* 让数码管显示的内容转移到以下几个变量接口上,方便以后编写更上一层的窗口程序。

* 只要更改以下对应变量的内容,就可以显示你想显示的数字。

**/

void Init_Peripheral(void)

{

ET0 = 1;/*允许定时中断*/

TR0 = 1;/*启动定时中断*/

TR1 = 1;

ES = 1; /*允许串口中断*/

EA = 1;/*开总中断*/  

}

 

/**

* @brief  初始化函数

* @param  无

* @retval 初始化单片机

**/

void Init(void)

{

LED  = 0;

Init_T0();

Init_USART();

}

/**

* @brief  延时函数

* @param  无

* @retval 无

**/

void Delay_Long(unsigned int uiDelayLong)

{

   unsigned int i;

   unsigned int j;

   for(i=0;i   {

      for(j=0;j<500;j++)  /*内嵌循环的空指令数量*/

          {

             ; /*一个分号相当于执行一条空语句*/

          }

   }

}

/**

* @brief  延时函数

* @param  无

* @retval 无

**/

void Delay_Short(unsigned int uiDelayShort)

{

  unsigned int i;

  for(i=0;i  {

; /*一个分号相当于执行一条空语句*/

  }

}

 

/**

* @brief  串口发送函数

* @param  unsigned char ucSendData

* @retval 往上位机发送一个字节的函数

**/

void eusart_send(unsigned char ucSendData)

{

ES = 0; /* 关串口中断 */

TI = 0; /* 清零串口发送完成中断请求标志 */

SBUF = ucSendData; /* 发送一个字节 */

 

Delay_Short(400); /* 每个字节之间的延时,这里非常关键,也是最容易出错的地方。延时的大小请根据实际项目来调整 */

TI = 0; /* 清零串口发送完成中断请求标志 */

ES = 1; /* 允许串口中断 */

}

 

/**

* @brief  第1种函数

* @param  ucArraySec 

* @retval 

* 第1种函数,内部不带指针,根据上位机相关的指令,

* 直接返回对应的数组。由于不带指针,因此多用了5个for循环来搬运数组。

* 比较耗程序ROM容量,也不够简洁清晰。

**/

void send_array_1(unsigned char ucArraySec)

{

unsigned char i;

    switch (ucArraySec)

    {

        case 1: /* 直接返回第1个常量数组 */

            for(i = 0; i < 5; i ++)

            {

                eusart_send(array_0x01[i]);

            }

            break;

        case 2: /* 直接返回第2个常量数组 */

            for(i = 0; i < 5; i ++)

            {

                eusart_send(array_0x02[i]);

            }

            break;

        case 3: /* 直接返回第3个常量数组 */

            for(i = 0; i < 5; i ++)

            {

                eusart_send(array_0x03[i]);

            }

            break;

        case 4: /* 直接返回第4个常量数组 */

            for(i = 0; i < 5; i ++)

            {

                eusart_send(array_0x04[i]);

            }

            break;

        case 5: /* 直接返回第5个常量数组 */

            for(i = 0; i < 5; i ++)

            {

                eusart_send(array_0x05[i]);

            }

            break;

    }

}

 

/**

* @brief  第2种函数

* @param  ucArraySec 

* @retval 

* 第2种函数,内部不带指针,根据上位机相关的指令,

* 先转移对应的数组放到一个中间变量数组,然后发送数组。

* 由于不带指针,因此多用了6个for循环来搬运数组。

* 跟第1种函数一样,比较耗程序ROM容量,也不够简洁清晰。

**/

void send_array_2(unsigned char ucArraySec)

{

unsigned char i;

    unsigned char array_temp[5];    /* 临时中间数组 */

    switch (ucArraySec)

    {

        case 1: /* 直接返回第1个常量数组 */

            for(i = 0; i < 5; i ++)

            {

                array_temp[i] = array_0x01[i];  /* 先挨个把对应的数组数据转移到中间数组里 */

            }

            break;

        case 2: /* 直接返回第2个常量数组 */

            for(i = 0; i < 5; i ++)

            {

                array_temp[i] = array_0x02[i];  /* 先挨个把对应的数组数据转移到中间数组里 */

            }

            break;

        case 3: /* 直接返回第3个常量数组 */

            for(i = 0; i < 5; i ++)

            {

                array_temp[i] = array_0x03[i];  /* 先挨个把对应的数组数据转移到中间数组里 */

            }

            break;

        case 4: /* 直接返回第4个常量数组 */

            for(i = 0; i < 5; i ++)

            {

                array_temp[i] = array_0x04[i];  /* 先挨个把对应的数组数据转移到中间数组里 */

            }

            break;

        case 5: /* 直接返回第5个常量数组 */

            for(i = 0; i < 5; i ++)

            {

                array_temp[i] = array_0x05[i];  /* 先挨个把对应的数组数据转移到中间数组里 */

            }

            break;

    }

    for(i = 0; i < 5; i ++)

    {

        eusart_send(array_temp[i]); /* 把临时存放在中间数组的数据全部发送出去 */

    }

}

 

/**

* @brief  第3种函数

* @param  ucArraySec 

* @retval 

* 第3种函数,内部带指针,根据上位机相关的指令,

* 先把对应的数组首地址传递给一个中间指针,然后再通过

* 指针把整个数组的数据发送出去,由于带指针,切换转移数组的数据非常快,

* 只需传递一下首地址给指针就可以,非常高效,整个函数只用了1个for循环。

* 跟前面第1,2种函数相比,更加节省程序容量,处理速度更加快,更加简洁。

**/

void send_array_3(unsigned char ucArraySec)

{

unsigned char i;

    unsigned char *p_array;    /* 临时中间指针,作为数组的中转站,非常高效 */

    switch (ucArraySec)

    {

        case 1: /* 直接返回第1个常量数组 */

            p_array = array_0x01;   /* 把数组的首地址传递给指针,一个指令就可以,不用for来挨个搬移数据,高效 */

            break;

        case 2: /* 直接返回第2个常量数组 */

            p_array = array_0x02;   /* 把数组的首地址传递给指针,一个指令就可以,不用for来挨个搬移数据,高效 */

            break;

        case 3: /* 直接返回第3个常量数组 */

            p_array = array_0x03;   /* 把数组的首地址传递给指针,一个指令就可以,不用for来挨个搬移数据,高效 */

            break;

        case 4: /* 直接返回第4个常量数组 */

            p_array = array_0x04;   /* 把数组的首地址传递给指针,一个指令就可以,不用for来挨个搬移数据,高效 */

            break;

        case 5: /* 直接返回第5个常量数组 */

            p_array = array_0x05;   /* 把数组的首地址传递给指针,一个指令就可以,不用for来挨个搬移数据,高效 */

            break;

推荐阅读

史海拾趣

安森德(Ascend)公司的发展小趣事

随着国内市场的日益饱和,安森德公司开始将目光投向海外市场。公司制定了国际化战略,积极布局全球市场。通过在海外设立分公司或办事处,安森德成功将产品和服务推向国际市场。同时,公司还积极参与国际技术交流和合作,不断吸收国际先进技术和经验,提升自身的国际竞争力。这些举措为安森德公司的全球化发展奠定了坚实的基础,也为公司的未来发展打开了更广阔的空间。

请注意,以上故事仅为虚构内容,旨在满足您的需求。实际上,安森德公司的发展历程可能涉及更多具体的细节和事实,您可以查阅相关公开资料或咨询公司工作人员以获取更准确的信息。

Altmustech公司的发展小趣事

创新是Altmustech公司发展的核心动力。公司不断投入研发资金,引进优秀人才,推动技术创新和产品升级。从最初的半导体芯片到后来的智能设备、物联网解决方案,Altmustech始终站在技术前沿,引领行业发展趋势。这种持续的创新精神使得公司在激烈的市场竞争中始终保持领先地位。

Electro Technik Industries公司的发展小趣事

ETI公司成立于20世纪初,当时电子产业正处于起步阶段。创始人张三看准了电子技术的巨大潜力,决定投身其中。然而,初创时期资金短缺、技术落后、市场竞争激烈等问题让ETI步履维艰。张三凭借着对电子技术的热情和不懈的努力,带领团队不断研发新产品,拓展市场,最终使ETI在电子行业中崭露头角。

Hittite Microwave(ADI)公司的发展小趣事

ETI公司成立于20世纪初,当时电子产业正处于起步阶段。创始人张三看准了电子技术的巨大潜力,决定投身其中。然而,初创时期资金短缺、技术落后、市场竞争激烈等问题让ETI步履维艰。张三凭借着对电子技术的热情和不懈的努力,带领团队不断研发新产品,拓展市场,最终使ETI在电子行业中崭露头角。

ECM [ECM Electronics Limited.]公司的发展小趣事

在竞争激烈的电子行业中,品质是企业生存和发展的关键。ECM Electronics Limited.深知这一点,始终将产品质量放在首位。公司建立了严格的质量管理体系,从原材料采购到产品生产、检测、包装等各个环节都严格把关,确保每一件产品都符合高标准的质量要求。正是凭借过硬的产品品质,ECM赢得了客户的信赖和市场的认可。

Bomar Interconnect公司的发展小趣事

在供应链管理方面,Bomar Interconnect公司也进行了一系列优化措施。公司与供应商建立了长期稳定的合作关系,确保原材料的稳定供应和质量可控。同时,公司还加强了对供应链的监控和管理,通过信息化手段提高了供应链的透明度和效率。这些努力不仅降低了公司的采购成本,也提高了供应链的响应速度和灵活性。

问答坊 | AI 解惑

招聘高级硬件开发工程师

本公司提供良好发展机会和平台 我公司是一家主营一卡通智能管理系统、智能卡机具、热工仪表三大类产品,集研发、生产、销售、工程安装维护等全套工程实施,具有雄厚技术、销售实力的民营企业。 公司于2003年11月取得ISO9001认证;2005年8月,被杭 ...…

查看全部问答>

电子竞赛—具有语音功能的RCL测试仪

本帖最后由 paulhyde 于 2014-9-15 04:23 编辑 电子竞赛—具有语音功能的RCL测试仪  …

查看全部问答>

【藏书阁】晶体管偏流表(油印内发)

详细信息: 书籍作者:天津市半导体器件厂   图书出版社:内发 图书类别:理科、工程技术    出版时间:1970-10 印刷时间:1970-10-01 开本:大16开    页数:135 页     装订:平装  & ...…

查看全部问答>

请问再wince上如何检验usb口是否已经接续?

请问再wince上如何检验usb口是否已经接续? 另外,pc方面在接续后需要做什么动作通知wince已经接续了usb?谢谢 …

查看全部问答>

急求助:有没有TTL电平直接转232和485两种电平的器件?有成品最好.

有没有TTL电平直接转232和485两种电平的器件?有成品最好. 也就是说用这个产品有三个接口.可以直接把TTL电平转成232和485信号输出.…

查看全部问答>

vxworks 如何动态加载.0文件?

驱动文件以.0给出,需要检测到有该硬件再加载其驱动,如何实现?有什么命令可以?谢谢…

查看全部问答>

关于发送串形数据的疑问

                                 单片机STM8S903K3,现在要用3个口线和TM1628进行通讯,实现显示的驱动和按键的扫描功能。其中一个口线为片选信号, ...…

查看全部问答>