📄 usarttest.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 + -