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

  • 编写子程序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    <p16f877A.inc>       ;调用头文件 
__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                              ; 程序结束

关于 “PIC单片机实现冒泡排序算法” 的 1 个意见

评论关闭。