网络消费网 >  5G > > 正文
第62节:大数据的加法运算
时间:2022-02-06 10:22:00
开场白:直接用C语言的“+”运算符进行加法运算时,“被加数”,“加数”,“和”,这三个数据的最大范围是unsigned long 类型,也就是数据最大范围是4个字节,十进制的范围是0至4294967295。一旦超过了这个范围,则运算会出错。因此,当进行大数据加法运算时,我们要额外编程序,实现大数据的算法。其实这种算法并不难,就是我们在小学里学的四则运算算法。 我们先要弄清楚一个新的概念。不考虑小数点的情况下,数据有两种表现形式。一种是常用的变量形式,另外一种是上一节讲到的BCD码数组形式。变量的最大范围有限,而BCD码数组的形式是无限的,正因为这个特点,所以我们可以进行大数据运算。 这一节要教大家两个知识点:第一个:如何通过用for循环语句改写上一节的组合BCD码跟非组合BCD码的转换函数。第二个:如何编写涉及到大数据加法运算的算法程序函数,同时也复习了指针的用途。第三个:如何在串口程序中通过关键字来截取所需要的数据。具体内容,请看源代码讲解。(1)硬件平台: 基于朱兆祺51单片机学习板。(2)实现功能:波特率是:9600 。通过电脑串口调试助手模拟上位机,往单片机发送组合BCD码的被加数和加数。单片机把组合BCD码的运算结果返回到上位机。最大范围4位,从0到9999,如果超范围则返回EE EE EE报错。往单片机发送的数据格式:EB 00 55 XX XX 0d 0aYY YY0d 0a指令,其中EB 00 55是数据头,XX 是被加数,可以是1个字节,也可以是2个字节。YY是加数,可以是1个字节,也可以是2个字节。0d 0a是固定的结束标志。例如:(a)1234+5678=6912上位机发送数据:eb 00 55 12 34 0d 0a 56 78 0d 0a单片机返回:69 12(b)9999+56=10055超过4位的9999,所以报错上位机发送数据:eb 00 55 99 990d 0a 56 0d 0a单片机返回:EE EE EE表示出错了(3)源代码讲解如下:#include "REG52.H"/* 注释一:* 本系统中,规定最大运算位数是4位。* 由于STC89C52单片机的RAM只有256个,也就是说系统的变量数最大* 不能超过256个,如果超过了这个极限,编译器就会报错。如果这个算法* 移植到stm32或者PIC等RAM比较大的单片机上,那么就可以把这个运算位数* 设置得更加大一点。*/#defineBCD4_MAX 2//本系统中,规定的组合BCD码最大字节数,一个字节包含2位,因此4位有效运算数#defineBCD8_MAX (BCD4_MAX*2)//本系统中,规定的非组合BCD码最大字节数,一个字节包含1位,因此4位有效运算数#define const_rc_size30//接收串口中断数据的缓冲区数组大小#define const_receive_time5//如果超过这个时间没有串口数据过来,就认为一串数据已经全部接收完,这个时间根据实际情况来调整大小#define uchar unsigned char //方便移植平台#define ulong unsigned long //方便移植平台//如果在VC的平台模拟此算法,则都定义成int类型,如下://#define uchar int//#define ulong intvoid initial_myself(void); void initial_peripheral(void);void delay_long(unsigned int uiDelaylong);void delay_short(unsigned int uiDelayShort);void T0_time(void);//定时中断函数void usart_receive(void); //串口接收中断函数void usart_service(void);//串口服务程序,在main函数里void eusart_send(unsigned char ucSendData);void BCD4_to_BCD8(const unsigned char *p_ucBCD_bit4,unsigned char ucBCD4_cnt,unsigned char *p_ucBCD_bit8,unsigned char *p_ucBCD8_cnt);void BCD8_to_BCD4(const unsigned char *p_ucBCD_bit8,unsigned char ucBCD8_cnt,unsigned char *p_ucBCD_bit4,unsigned char *p_ucBCD4_cnt);void ClearAllData(uchar ucARRAY_MAX,uchar *destData);uchar GetDataLength(const uchar *destData,uchar ucARRAY_MAX);uchar AddData(const uchar *destData,const uchar *sourceData,uchar *resultData);sbit beep_dr=P2^7; //蜂鸣器的驱动IO口unsigned intuiSendCnt=0; //用来识别串口是否接收完一串数据的计时器unsigned char ucSendLock=1; //串口服务程序的自锁变量,每次接收完一串数据只处理一次unsigned intuiRcregTotal=0;//代表当前缓冲区已经接收了多少个数据unsigned char ucRcregBuf[const_rc_size]; //接收串口中断数据的缓冲区数组unsigned intuiRcMoveIndex=0;//用来解析数据协议的中间变量unsigned char ucDataBCD4_1[BCD4_MAX]; //接收到的第1个数组合BCD码数组形式这里是指被加数unsigned char ucDataBCD4_cnt_1=0;//接收到的第1个数组合BCD码数组的有效数据长度unsigned char ucDataBCD4_2[BCD4_MAX]; //接收到的第2个数组合BCD码数组形式这里是指加数unsigned char ucDataBCD4_cnt_2=0;//接收到的第2个数组合BCD码数组的有效数据长度unsigned char ucDataBCD4_3[BCD4_MAX]; //接收到的第3个数组合BCD码数组形式这里是指和unsigned char ucDataBCD4_cnt_3=0;//接收到的第3个数组合BCD码数组的有效数据长度unsigned char ucDataBCD8_1[BCD8_MAX]; //接收到的第1个数非组合BCD码数组形式 这里是指被加数unsigned char ucDataBCD8_cnt_1=0;//接收到的第1个数非组合BCD码数组的有效数据长度unsigned char ucDataBCD8_2[BCD8_MAX]; //接收到的第2个数非组合BCD码数组形式 这里是指加数unsigned char ucDataBCD8_cnt_2=0;//接收到的第2个数非组合BCD码数组的有效数据长度unsigned char ucDataBCD8_3[BCD8_MAX]; //接收到的第3个数非组合BCD码数组形式 这里是指和unsigned char ucDataBCD8_cnt_3=0;//接收到的第3个数非组合BCD码数组的有效数据长度unsigned char ucResultFlag=11; //运算结果标志,10代表计算结果超出范围出错,11代表正常。void main(){ initial_myself(); delay_long(100); initial_peripheral(); while(1) { usart_service();//串口服务程序 }}/* 注释二:* 组合BCD码转成非组合BCD码。* 这里的变量ucBCD4_cnt代表组合BCD码的有效字节数.* 这里的变量*p_ucBCD8_cnt代表经过转换后,非组合BCD码的有效字节数,记得加地址符号&传址进去* 本程序在上一节的基础上,略作修改,用循环for语句压缩了代码,* 同时引进了组合BCD码的有效字节数变量。这样就不限定了数据的长度,* 可以让我们根据数据的实际大小灵活运用。*/void BCD4_to_BCD8(const unsigned char *p_ucBCD_bit4,unsigned char ucBCD4_cnt,unsigned char *p_ucBCD_bit8,unsigned char *p_ucBCD8_cnt){ unsigned char ucTmep; unsigned char i; for(i=0;i>4; p_ucBCD_bit8[ucBCD4_cnt*2-i*2-2]=ucTmep&0x0f; }}/* 注释三:* 非组合BCD码转成组合BCD码。* 这里的变量ucBCD8_cnt代表非组合BCD码的有效字节数.* 这里的变量*p_ucBCD4_cnt代表经过转换后,组合BCD码的有效字节数,记得加地址符号&传址进去* 本程序在上一节的基础上,略作修改,用循环for语句压缩了代码,* 同时引进了非组合BCD码的有效字节数变量。这样就不限定了数据的长度,* 可以让我们根据数据的实际大小灵活运用。*/void BCD8_to_BCD4(const unsigned char *p_ucBCD_bit8,unsigned char ucBCD8_cnt,unsigned char *p_ucBCD_bit4,unsigned char *p_ucBCD4_cnt){ unsigned char ucTmep; unsigned char i; unsigned char ucBCD4_cnt; for(i=0;i=sourceCnt)//找出两个运算数据中最大的有效位数{ maxCnt=destCnt;}else{ maxCnt=sourceCnt;}for(i=0;i=const_receive_time&&ucSendLock==1) //说明超过了一定的时间内,再也没有新数据从串口来 { ucSendLock=0; //处理一次就锁起来,不用每次都进来,除非有新接收的数据 //下面的代码进入数据协议解析和数据处理的阶段 uiRcMoveIndex=0; //由于是判断数据头,所以下标移动变量从数组的0开始向最尾端移动 while(uiRcMoveIndexinterrupt1 //定时中断{TF0=0;//清除中断标志TR0=0; //关中断if(uiSendCntconst_rc_size)//超过缓冲区 { uiRcregTotal=const_rc_size; } ucRcregBuf[uiRcregTotal-1]=SBUF; //将串口接收到的数据缓存到接收缓冲区里 uiSendCnt=0;//及时喂狗,虽然main函数那边不断在累加,但是只要串口的数据还没发送完毕,那么它永远也长不大,因为每个中断都被清零。 } else//发送中断,及时把发送中断标志位清零 { TI = 0; } } void delay_long(unsigned int uiDelayLong){ unsigned int i; unsigned int j; for(i=0;i三极管控制蜂鸣器,输出高电平时不叫。//配置定时器TMOD=0x01;//设置定时器0为工作方式1TH0=0xfe; //重装初始值(65535-500)=65035=0xfe0bTL0=0x0b;//配置串口SCON=0x50;TMOD=0X21;TH1=TL1=-(11059200L/12/32/9600);//这段配置代码具体是什么意思,我也不太清楚,反正是跟串口波特率有关。TR1=1;}void initial_peripheral(void) //第二区 初始化外围{ EA=1; //开总中断 ES=1; //允许串口中断 ET0=1; //允许定时中断 TR0=1; //启动定时中断}总结陈词:既然这节讲了加法程序,那么下一节接着讲常用的减法程序,这种大数据的减法程序是什么样的?欲知详情,请听下回分解----大数据的减法运算。

关键词: 大数据加法运

版权声明:
    凡注明来网络消费网的作品,版权均属网络消费网所有,未经授权不得转载、摘编或利用其它方式使用上述作品。已经本网授权使用作品的,应在授权范围内使用,并注明"来源:网络消费网"。违反上述声明者,本网将追究其相关法律责任。
    除来源署名为网络消费网稿件外,其他所转载内容之原创性、真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考并自行核实。
热文

网站首页 |网站简介 | 关于我们 | 广告业务 | 投稿信箱
 

Copyright © 2000-2020 www.sosol.com.cn All Rights Reserved.
 

中国网络消费网 版权所有 未经书面授权 不得复制或建立镜像
 

联系邮箱:920 891 263@qq.com

备案号:京ICP备2022016840号-15

营业执照公示信息