⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usarttest.asm

📁 AVR开发例程 有多种设计样例 帮你快速掌控AVR
💻 ASM
字号:
;本程序中为进行RS232串行通信的测试程序。程序的功能是单片机ATmega16首先接收来自计算机
;的字符,然后再将接收到的字符,发送给计算机。

.include "m16def.inc"   ;文件头,其中包含ATmega16芯片的硬件资源定义,针对ATmega16的
                        ;程序一般需要有此指令。

.org  $0000             ;org是一条伪指令,表示随后程序的起始位置。即表示下条指令
                        ;"rjmp	RESET"位于程序存储器的$0000地址

    rjmp	RESET		;单片机复位后从$0000开始执行程序,在这里放一条跳转指令,
	                    ;跳转到主程序开始的地址
	

.org $0020	            ;$0000地址之后是中断向量区,跳过中断区。中断与中断向量将在
                        ;以后解释,可以参考光盘中ATmega16的数据手册。
RESET:

	ldi	r16,high(RAMEND) 
	out	SPH,r16	          
	ldi	r16,low(RAMEND)	 ;设置堆栈,一般将堆栈设置到RAM的结尾。
	out	SPL,r16          ;在自己编写程序时,可以使用以上代码

	
	ldi r16,0b11111111   ;
	out DDRA,r16
	out DDRC,r16
	out DDRD,r16            ;设置PA,PB,PC,PD端口全部为输出

	ldi r16,0b11111110;
	out DDRB,r16         ;设置PB0为输入,PB0管脚连接按键

	ldi r16,0b11111111;
	out PORTA,r16        ;PA端口全部输出高电平,LED熄灭
	out PORTC,r16        
	out PORTD,r16		 ;PC端口,PD端口输出高电平
	out PORTB,r16        ;PB1~PB7输出高电平,PB0为输入,打开内部上拉;  端口的初始化完成。

    ;USART的初始化

	ldi r16,95        ;将10进制数95送入寄存器r16。晶体14.7456MHZ,波特率9600,可以算出UBRR应为95
	ldi r17,0
	out UBRRH,r17     ;设置波特率高位。由于UBRRH的复位默认值为0,所以此句可以省略
	out UBRRL,r16     ;设置波特率低位。 波特率设置完成。
	
	ldi r16,0b00011000 ;将2进制数0b00011000送入寄存器r16
	out UCSRB,r16   ;RXEN,TXEN被写为1,允许USART进行接收和发送
	                
					;此处没有对USART寄存器UCSRA操作。USART的复位默认值为0,等同于‘ldi r16,0b00000000;
					;out UCSRA,r16’的运行结果。此处省略这2句程序,写上这2句也可以。
					;UCSRA中位RXC,TXC,UDRE主要由硬件
					;操作,程序主要读取判断这些位;FE接收帧出错,DOR接受数据溢出出错,PE校验错误只能由硬件
					;操作,并且在普通的串口编程应用中这些错误判断位比较使用的比较少;U2X为0,表示没有使用
					;倍速模式;MPCM为0,表示不使用多机通信。    
	
	ldi r16,0b10000110 ;
	out UCSRC,r16    ;位7 URSEL必须为1,才能正常写UCSRC;
	                 ;位6 UMSEL为0,选择异步模式
					 ;位5,4 UPM1,UPM0为0b00,选择无校验模式
					 ;位3,USBS为0,选择1位停止位
					 ;位2,1 UCSZ1,UCSZ0为0b11,加上UCSRB中UCSZ2为0,即组成0b011,选择8位数据
					 ;位0,UCPOL为0,异步模式下该位必须设置为0

					 ;USART初始化完成


MAIN:   ;主程序实现的功能:接收到一个字符,再将这个字符回送出来
    
	sbis UCSRA,RXC   ;参考指令集中关于‘sbis’的使用方法;测试UCSRA中RXC是否为1,为1跳1行执行,为0,顺序执行
	rjmp MAIN        ;RXC为 0,说明数据还没有接收完毕,继续检测RXC位,
	in r16,UDR       ;RXC为1时,程序跳至此处,数据已经接收完毕,将数据从UDR中读入工作寄存器r16
                    
                     
					 ;接受到数据以后,再将数据返回;首先发送固定字符“The char is:”。 
					 ;以下程序虽能满足功能,却繁琐,请查阅指令集,选择合适的指令及伪指令简化之。
TX_CHECK1:
	sbis UCSRA,UDRE  ;
    rjmp TX_CHECK1   ;检测UDRE是否为1,若为0,说明UDR寄存器没有准备好,跳到TX_CHECK1继续检测
	ldi r17,'T'      ;为1,跳一行程序跳到此处,UDR寄存器已经准备完毕,将字符‘T’发送出去。
	out UDR,r17      ;
TX_CHECK2:
	sbis UCSRA,UDRE  ;
    rjmp TX_CHECK2   ;
	ldi r17,'h'      ;
	out UDR,r17      ;发送字符‘h’。
TX_CHECK3:
	sbis UCSRA,UDRE  ;
    rjmp TX_CHECK3   ;
	ldi r17,'e'      ;
	out UDR,r17      ;发送字符‘e’。    
TX_CHECK4:
	sbis UCSRA,UDRE  ;
    rjmp TX_CHECK4   ;
	ldi r17,' '      ;
	out UDR,r17      ;发送字符空格。	
TX_CHECK5:
	sbis UCSRA,UDRE  ;
    rjmp TX_CHECK5   ;
	ldi r17,'c'      ;
	out UDR,r17      ;发送字符‘c’。
TX_CHECK6:
	sbis UCSRA,UDRE  ;
    rjmp TX_CHECK6   ;
	ldi r17,'h'      ;
	out UDR,r17      ;发送字符‘h’。
TX_CHECK7:
	sbis UCSRA,UDRE  ;
    rjmp TX_CHECK7   ;
	ldi r17,'a'      ;
	out UDR,r17      ;发送字符‘a’。
TX_CHECK8:
	sbis UCSRA,UDRE  ;
    rjmp TX_CHECK8   ;
	ldi r17,'r'      ;
	out UDR,r17      ;发送字符‘r’。	
TX_CHECK9:
	sbis UCSRA,UDRE  ;
    rjmp TX_CHECK9   ;
	ldi r17,' '      ;
	out UDR,r17      ;发送字符空格。
TX_CHECK10:
	sbis UCSRA,UDRE  ;
    rjmp TX_CHECK10  ;
	ldi r17,'i'      ;
	out UDR,r17      ;发送字符‘i’。	
TX_CHECK11:
	sbis UCSRA,UDRE  ;
    rjmp TX_CHECK11   ;
	ldi r17,'s'      ;
	out UDR,r17      ;发送字符‘s’。
TX_CHECK12:
	sbis UCSRA,UDRE  ;
    rjmp TX_CHECK12   ;
	ldi r17,':'      ;
	out UDR,r17      ;发送字符‘:’。需要简化的部分到此处

TX_CHECK13:
	sbis UCSRA,UDRE  ;
    rjmp TX_CHECK13  ;
	mov r17,r16      ;r16中保存的是刚刚接收到的数据,将它送入r17,然后发送出去,
	out UDR,r17      ;也就实现了程序的目的,接收到数据然后回送。

TX_CHECK14:
	sbis UCSRA,UDRE  ;
    rjmp TX_CHECK14  ;
	ldi r17,'.'      ;
	out UDR,r17      ;发送字符句号。
TX_CHECK15:
	sbis UCSRA,UDRE  ;
    rjmp TX_CHECK15  ;
	ldi r17,0x0d     ;
	out UDR,r17      ;回车
TX_CHECK16:
	sbis UCSRA,UDRE  ;
    rjmp TX_CHECK16  ;
	ldi r17,0x0a     ;
	out UDR,r17      ;换行。可以去掉回车换行程序观察运行效果。

	

	rjmp MAIN        ;跳到主程序开始,开始下个字符的接收与回送。

;数据的传送需要注意:32个工作寄存器(r0~r31)之间传送数据用指令‘mov’,如‘mov r17,r16’
;立即数送工作寄存器(只能是r16~r31)使用指令‘ldi’,如‘ldi r16,95’;‘ldi r14,95’是错误用法
;32个工作寄存器(r0~r31)和I/O口空间(包括端口,各种配置寄存器)传送数据使用指令‘in’和‘out’,
  ;如‘out PORTA,r16’,‘in r16,UDR ’,‘out UDR,r17’等。
;立即数不能直接送I/O口空间,需要先将立即数送入工作寄存器,然后送入I/O空间。如‘ldi r16,0b11111111;out PORTA,r16’等等。  	
;可以参考ATmega16的指令集获得更多详细内容和指令的使用方法。	
	
	
	
	
	
	
	
	
	
	
	
	

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -