所以我正在学习ASM,并拥有一台LM4F120XL ARM Cortex-M4 MCU。 我正在使用Keil uVision V4.54。
我熟悉设置端口等,初始化GPIO和UART。
我所坚持的是通过连续读取和写入TeraTerm / Putty,例如。
我理解RxFE = 0,FIFO不为空 - 从中读取; 并且TxFF = 0,FIFO未满 - 写入它..
但是在比较并满足这些条件之后,我实际上写了什么数据到UART_DR,数据寄存器......?仅仅是将数据寄存器加载到寄存器中,将该地址的值加载到另一个寄存器中,然后......即使不更改位,我也会丢失,而不是添加新数据 - 然后你就是' d将它从该寄存器存储回数据寄存器寄存器..
因此,如果数据寄存器中存在数据,那么它将被及时传出..? 我可以使用正确的COM端口连接到TeraTerm,调整BAUD和PARITY设置..但是如果数据寄存器中存在数据,那么在适当的周期之后它会自动发送..?
另外,从键盘读取字符怎么样?或者其他计算机外围设备..问题是 - 知道地址,将值加载到寄存器中,然后将其存储到数据寄存器中?如果数据寄存器保存数据,那么这需要非破坏性地完成..
为什么用C ++而不是ASM编写的每一篇关于MCU编码的文章呢? 我也学习C ++,但不知道为什么没有人使用汇编/机器代码..
; -------
ReadChar
PUSH {R0, R1}
inloop LDR R0,= UART_FR LDR R1,[R0] AND R1,#0x10 CMP R1,#0x0 BNE inloop
LDR R0, =UART_DR
LDR R1, [R0]
************??
STR R1, [R0]
POP {R0, R1}
BX LR
; -------
OutputChar
PUSH {R0, R1}
outloop LDR R0,= UART_FR LDR R1,[R0] AND R1,#0x20 CMP R1,#0x0 BNE outloop
LDR R0, =UART_DR
LDR R1, [R0]
************??
STR R1, [R0]
POP {R0, R1}
BX LR
; -------
答案 0 :(得分:1)
是的,您正在编写串行/ uart界面上的字符。如果您使用哑终端,ASCII是最容易使用的。一个简单的测试循环:
unsigned char ra;
...
for(ra=0;;ra++)
{
ra&=7;
UART_DR = 0x30+ra;
timed_delay();
}
其中定时延迟比发送字符所需的时间长(10位周期,开始,数据,停止,无论9600,115200等等,还是长时间延迟)
然后
unsigned char ra;
...
for(ra=0;;ra++)
{
ra&=7;
uart_putc(ra);
}
其中uart_putc在这种情况下等待tx缓冲区/ fifo中有一个空格,然后插入传递给该fifo的值。
您的终端将显示的是01234567(您可能想告诉它换行)。如果第二个程序不是01234567,而是那些03715的那些......那么你不是在等待tx为空。
答案 1 :(得分:1)
听起来你还没有完全理解这种'注册'是如何运作的。不要把它当作保存数据的存储盒(比如CPU的通用寄存器),把它想象成一个邮箱 - 当你写一个字节时,那个字节被带入Tx FIFO缓冲区,但是当你从它读取时,你会得到一个从Rx FIFO传送的字节。通过读 - 修改 - 写操作改变位的想法确实没有意义,因为读和写这样的寄存器意味着完全不同的东西。
传输一个字节(一旦设置完成)就像这样简单:
; byte to transmit is in r0
; <wait for space in Tx FIFO>
LDR r1, =UART_DR
STRB r0, [r1]
一旦你写入FIFO,你的工作(作为软件)就完成了,你可以让硬件负责将缓冲区的内容传输到线路。
接收大致相同,但阅读而非写作:
; <wait for data in Rx FIFO>
LDR r1, =UART_DR
LDRB r0, [r1]
; received byte now in r0
根据MCU的the TRM(我认为这是合适的,部件号似乎已经改变),数据字节上方有一些只读接收状态位,因此您可以更改{{1} } LDRB
来捕捉数据旁边的那些,但在这种情况下我真的不会打扰 - 串行通信的内部工作方式与学习装配完全相同。