本帖最后由 MouseesuoM 于 2015-2-4 17:41 编辑
我记得在GPIO流水灯的时候,是用宏自己定义的寄存器(#define (*(volatile unsigned *) 寄存器的地址)),那个程序是可行的,但是在串口实验中用自己定义的寄存器来进行操作时,每当给UART0_C2赋值的时候,程序就跳转到启动代码(.S文件)中的 HardFault_Handler 自己也琢磨了好几天 始终不明白为什么(我会把这个代码上传希望高手能解答一下)。所以也就放弃了自己定义寄存器的想法。而是转用别人定义的寄存器来操作的。 下面进入主题,当然自己在编写代码过程中也遇到很多问题,希望各位好友知道的能给解答一下。
(一)
其实KL25芯片许多引脚都可以用来当做串口的输入输出:PA1 PA2,PA14 PA15,PD6 PD7 ,PE20 PE21,PE16 PE17,那么你怎么知道这些引脚可以当做串口来使用?而且你是怎么选择使用哪一对来进行编程的?
引脚的复用功能(所谓复用就是除了普通的GPIO的输入输出功能还有额外的功能,比如说今天的串口的发送接收引脚,比如说的用来当做SPI通讯的接收、输出、时钟、片选引脚等),这些功能需要查看数据手册的 10.3.1节 KL25信号复用和引脚列表,那么这些东西就不难知道了。那具体实际需要编程哪个引脚呢?那么就要看原理图了,
从原理图上不难发现是用的PA1 和PA2,自己当时还很傻的用PE20 和P21 来进行编程,真是感觉傻到家了。 当然如果要使用PA1 PA2 就是要对着两个引脚初始化,那么要特别注意,在PCR寄存器(引脚控制寄存器中),这两个引脚的控制寄存器的MUX位要设置为010,因为用的是这两个引脚的第二复用功能,所以是010,以此类推,如果用的是第五复用功能(一共是七个),那么就是101了。
(二)
下来,就要确定该怎么编程了,其实我们不难发现,一般串口就那些设置,波特率、起始位、数据位、奇偶校验、流控制等等,一般来说对于我们就足够了。
我们要的是串口0,关于串口0的介绍在数据手册的第39章。
下来卡数据手册:
1、首先第一个寄存器是设置波特率的,他是由两个寄存器(UART0_BDH UART0_BLH)确定的,具体组成是UART0_BDH 的低5位和UART0_BLH全部8位 共13位构成。(看到这里我也是醉了,cotex-m0到底是多少位的芯片,怎么还能出来8位宽的寄存器了?)
接着往下说,那么不难发现波特率的计算公式
UART 波特率=UART 模块时钟/((OSR+1)*BR
(1)那么第一个问题来了,UART模块时钟是多少?
在数据手册 第五章中不难发现 UART0的时钟分配
我们不难发现UART0的时钟源设置由SIM_SOPT2寄存器控制的,我们找到这个寄存器(具体的寄存器大家还是去看数据手册,这里我就不给贴出来),其中关于UART0的时钟源选择的控制位是D27:D26
D27~26(UART0SRC)—UART0 时钟源选择。
为 UART0 发送和接收时钟选择时钟源。00 禁用时钟; 01 MCGFLLCLK 时钟或 MCGPLLCLK/2 时钟; 10 OSCERCLK 时钟; 11MCGIRCLK 时钟。
在本次实验中,我们选择MCGPLL/2,也就是说[D27:D26]为01。
同时该寄存器的D16位也要设置为1。通俗点讲就是到底用哪个时钟为外设提供时钟。这里我们用MCGPLL/2,自然D16要写入1(发现中文数据对这一位的叙述正好写反了。)
那么MCGPLL/2=?,我们在startup_MKL25Z4.s启动代码中不难发现:
LDRR0,=SysytemInit 这行代码,具体是什么意思我不清楚还请高人指教,但是大概意思是就是在系复位后,会调用SystemInit函数,那么SystemInit函数在哪呢?-----在system_MKL25Z4.c中,在这个C文件中可以找到SystemInit函数,具体我就不贴出来,这段函数主要是对系统等一些时钟的设置大家想了解可以自己看。
在system_MKL25Z4.c中CLOCK_SETUP选择的是1,
所以调用SystemInit函数后, MCGIRCLK(4000Khz),MCGPLL (48000Khz)
BUSCLK(24000khz)。【这里关于时钟的问题,理解是不正确的大家可以参考一下12楼】
所以UART0的模块配置完后是时钟24Mhz。(其实就是BusClock)。
(2)OSR的确定
OSR是由UART0控制寄存器4中的[D4:D0]来确定的,默认的复位值是01111 页就是OSR=16。
在本次实验中,波特率115200,所以带入上述的公式,不难确定BR=13(00000 00001101),所以在UART0_BDH的低5位全部写0,而UART0_BLH写入 0x0D即可。
关于UART0_BDH的D5是停止位的选择,我们设置为1位(默认即可),其余两个是关于中断机制的串口通讯我们不用管也是默认。
2、UART0_C1(串口控制寄存器1)
这里我们只需要处理标记的位就可以(具体内容还是看数据手册吧):
LOOPS:0--采用不同的引脚正常操作UART_TX、UART_RX
M :数据位的选择 0对应的是8位模式
PE :奇偶校验 0 不使能
PT :是奇校验还是偶校验(这里不用管 默认就可以了)
3、UART0_C2(串口控制寄存器2)
TE:发送器使能位
RE:接收器使能位
其余位默认即可,不用去设置。
这里在多讲一点,所有关于波特率的设置,控制寄存器的操作设置,必须发送 接收器禁止才能设置,一旦使能就不要在操作这些寄存器了。
4、UART0_S1(UART0状态寄存器)
TDRE:复位值 是 1,表示发送缓冲器是空的,当向写 UART 数据寄存器( UART_D),其值变为0 表示发送缓冲器满。
这里我个人认为 TDRE是不会自动置1的,所以还需要在代码中自己操作寄存器实现置1(本人经过试验发现的,如有不对请指正)。
TC:发送完成标志。 1:发送完成。写 UART 数据寄存器( UART_D)来发送新的
数据,TC 被自动清除变为0。
RDRF:RDRF=0, 接收数据寄存器空; RDRF=1,接收数据寄存器满。
其余位 默认就可以。
5、UART0_D(UART数据寄存器)
这个没什么好说的了,如果要发送数据,需要向该寄存器写入值。如果接受数据,数据会保存在该寄存器中。在读写该寄存器时,某些寄存器位会自动置位或者清除,这里我就不说了,大家看数据手册就可以。
Polling机制的串口通讯差不多就这些操作就够了。所谓Polling机制就是轮训的机制,不断的查询。
还有建立工程时,用的别人实现的寄存器(好像是周立功用官方库实现的),下载的话大家可以根据这个帖子
https://bbs.elecfans.com/forum.php?mod=viewthread&tid=463417,自己随便找个例子修改修改就可了。具体的操作我会在发个帖子。
最后上传下自己的代码
UART2.rar
(457.8 KB)
(下载次数: 116, 2015-1-22 21:52 上传)