PIC单片机实现冒泡排序算法

2019-04-15 11:48发布

  • 编写子程序paixu,实现1Byte数的顺序排列。待排序的10个二进制数(自定义数据大小)存放在内存空间内。
  • 编写宏定义实现大小比较和换位,入口参数为待比较的两个数据地址。
  • 注意排序过程中需要使用间接寻址方式,即利用FSR和INDF两个特殊功能寄存器实现寻址操作。
  • 编写子程序,调用宏定义,使用冒泡排序算法实现排序。

1、冒泡排序算法

冒泡排序是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。 冒泡排序算法的运作如下:
  • 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
  • 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
  • 针对所有的元素重复以上的步骤,除了最后一个。
  • 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

2、编写宏定义实现大小比较与换位

程序框图PIC冒泡排序算法-比较与交换 ;*****************宏定义********************************************************* compare_swap macro DATAI,DATAJ,TEMP BCF STATUS,C ; 标志位清零 MOVF DATAJ,W SUBWF DATAI,W ; 比较大小 BTFSC STATUS,C ; TEMP1>TEMP2? GOTO NEXT1 GOTO NEXT2 NEXT1 swap DATAI,DATAJ,TEMP ; 是,则交换两者的值 NEXT2 nop ; 否则,不做操作 endm swap macro DATAI,DATAJ,TEMP MOVF DATAI,W MOVWF TEMP MOVF DATAJ,W MOVWF DATAI MOVF TEMP,W MOVWF DATAJ endm 进行宏指令嵌套时,要十分注意宏指令调用与子程序调用的区别,否则很容易产生错误。例如下面这段代码: BTFSC STATUS,C ; TEMP1>TEMP2? GOTO NEXT1 GOTO NEXT2 NEXT1 swap DATAI,DATAJ,TEMP ; 是,则交换两者的值 NEXT2 nop 如不慎写作: BTFSC STATUS,C ; TEMP1>TEMP2? swap DATAI,DATAJ,TEMP ; 是,则交换两者的值 nop ; 否则,不做操作 就会发生错误。

3、编写子程序,调用宏定义实现排序

子程序框图:PIC冒泡排序 ;*************************子程序************************** ******************** ORG 0x0100 paixu LOOP1 MOVLW 0x20 MOVWF FSR ; FSR=0x20,起始位置 CLRF COUNT2 LOOP2 MOVF INDF,W MOVWF DATAI INCF FSR,F MOVF INDF,W MOVWF DATAJ compare_swap DATAI,DATAJ,TEMP MOVF DATAJ,W ; 数据还原 MOVWF INDF DECF FSR,F MOVF DATAI,W MOVWF INDF INCF FSR,F INCF COUNT2,F ; COUNT2++,COUNT2<9-COUNT1? MOVF COUNT1,W SUBWF SIZE,W BSF STATUS,C SUBWF COUNT2,W BTFSS STATUS,C GOTO LOOP2 INCF COUNT1,F ; COUNT1++,COUNT1<9? BSF STATUS,C MOVF SIZE,W SUBWF COUNT1,W BTFSS STATUS,C GOTO LOOP1 NOP RETURN ;*****************************************************************************

完整程序: list p=16f877A ;标明所用的处理器类型 #include ;调用头文件 __CONFIG _CP_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_OFF & _HS_OSC & _WRT_OFF & _LVP_OFF & _CPD_OFF ;*****************宏定义********************************************************* compare_swap macro DATAI,DATAJ,TEMP BCF STATUS,C ; 标志位清零 MOVF DATAJ,W SUBWF DATAI,W ; 比较大小 BTFSC STATUS,C ; TEMP1>TEMP2? GOTO NEXT1 GOTO NEXT2 NEXT1 swap DATAI,DATAJ,TEMP ; 是,则交换两者的值 NEXT2 nop ; 否则,不做操作 endm swap macro DATAI,DATAJ,TEMP MOVF DATAI,W MOVWF TEMP MOVF DATAJ,W MOVWF DATAI MOVF TEMP,W MOVWF DATAJ endm ;*****************变量定义******************************************************* DATA1 EQU 0x20 ; 待排序的数据 DATA2 EQU 0x21 DATA3 EQU 0x22 DATA4 EQU 0x23 DATA5 EQU 0x24 DATA6 EQU 0x25 DATA7 EQU 0x26 DATA8 EQU 0x27 DATA9 EQU 0x28 DATA10 EQU 0x29 SIZE EQU 0x30 ; 待排序数据个数-1 COUNT1 EQU 0x31 ; 循环变量 COUNT2 EQU 0x32 TEMP EQU 0x33 ; 临时变量 DATAI EQU 0x34 DATAJ EQU 0x35 ;******************************************************************************* ORG 0x0000 ; 复位入口地址 nop ; 兼容ICD调试工具,必须加nop goto Main ; 跳转至Main函数 ;*************************Main 函数的代码*************************************** Main MOVLW 0x34 ; 数据初始化 MOVWF DATA1 MOVLW 0x53 MOVWF DATA2 MOVLW 0xb5 MOVWF DATA3 MOVLW 0x33 MOVWF DATA4 MOVLW 0xA1 MOVWF DATA5 MOVLW 0x42 MOVWF DATA6 MOVLW 0x11 MOVWF DATA7 MOVLW 0x86 MOVWF DATA8 MOVLW 0x65 MOVWF DATA9 MOVLW 0x76 MOVWF DATA10 MOVLW .9 MOVWF SIZE CLRF COUNT1 ; 初始化循环变量 CLRF COUNT2 CLRF TEMP ; 初始化临时变量 CLRF DATAI CLRF DATAJ CALL paixu ; 调用子程序排序 nop goto $ ; 停机 ;*************************子程序************************** ******************** ORG 0x0100 paixu LOOP1 MOVLW 0x20 MOVWF FSR ; FSR=0x20,起始位置 CLRF COUNT2 LOOP2 MOVF INDF,W MOVWF DATAI INCF FSR,F MOVF INDF,W MOVWF DATAJ compare_swap DATAI,DATAJ,TEMP MOVF DATAJ,W ; 数据还原 MOVWF INDF DECF FSR,F MOVF DATAI,W MOVWF INDF INCF FSR,F INCF COUNT2,F ; COUNT2++,COUNT2<9-COUNT1? MOVF COUNT1,W SUBWF SIZE,W BSF STATUS,C SUBWF COUNT2,W BTFSS STATUS,C GOTO LOOP2 INCF COUNT1,F ; COUNT1++,COUNT1<9? BSF STATUS,C MOVF SIZE,W SUBWF COUNT1,W BTFSS STATUS,C GOTO LOOP1 NOP RETURN ;***************************************************************************** END ; 程序结束