本实验的源码工程在开发板光盘资料的:i.MX6UL终结者光盘资料\04_裸机例程源码\12_uart 目录下。我们在Ubuntu系统下使用命令“mkdir 12_uart”建立“12_uart”文件夹,如图 1所示:
然后使用“cd 12_uart”命令进入到12_uart文件夹,如图 2所示:
然后使用命令“cp -r …/11_gpt_delay/* ./”将上一章试验中的所有内容拷贝到刚刚新建的“12_uart”里面,如图 3所示:
然后在drivers目录下建立uart文件夹,用来保存uart的驱动文件,然后在“drivers/uart”目录中新建uart.h和uart.c两个文件,然后在uart.h文件输入下面的代码:
1 #ifndef _BSP_UART_H
2 #define _BSP_UART_H
3 #include "imx6ul.h"
4
5 /* 函数声明 */
6 void uart_init(void);
7 void uart_io_init(void);
8 void uart_disable(UART_Type *base);
9 void uart_enable(UART_Type *base);
10 void uart_softreset(UART_Type *base);
11 void uart_setbaudrate(UART_Type *base, unsigned int baudrate, unsigned int srcclock_hz);
12 void putc(unsigned char c);
13 void puts(char *str);
14 unsigned char getc(void);
15 void raise(int sig_nr);
16
17
18 #endif
uart.h里面主要是声明了一些函数,然后我们打开“drivers/usrt.c”文件,在里面输入下面的内容:
1 #include "uart.h"
2
3 /*
4 * @description : 初始化串口1,波特率为115200
5 * @param : 无
6 * @return : 无
7 */
8 void uart_init(void)
9 {
10 /* 1、初始化串口IO */
11 uart_io_init();
12
13 /* 2、初始化UART1 */
14 uart_disable(UART1); /* 先关闭UART1 */
15 uart_softreset(UART1); /* 软件复位UART1 */
16
17 UART1->UCR1 = 0; /* 先清除UCR1寄存器 */
18
19 /*
20 * 设置UART的UCR1寄存器,关闭自动波特率
21 * bit14: 0 关闭自动波特率检测,我们自己设置波特率
22 */
23 UART1->UCR1 &= ~(1<<14);
24
25 /*
26 * 设置UART的UCR2寄存器,设置内容包括字长,停止位,校验模式,关闭RTS硬件流控
27 * bit14: 1 忽略RTS引脚
28 * bit8: 0 关闭奇偶校验
29 * bit6: 0 1位停止位
30 * bit5: 1 8位数据位
31 * bit2: 1 打开发送
32 * bit1: 1 打开接收
33 */
34 UART1->UCR2 |= (1<<14) | (1<<5) | (1<<2) | (1<<1);
35
36 /*
37 * UART1的UCR3寄存器
38 * bit2: 1 必须设置为1!参考IMX6ULL参考手册3624页
39 */
40 UART1->UCR3 |= 1<<2;
41
42 /*
43 * 设置波特率
44 * 波特率计算公式:Baud Rate = Ref Freq / (16 * (UBMR + 1)/(UBIR+1))
45 * 如果要设置波特率为115200,那么可以使用如下参数:
46 * Ref Freq = 80M 也就是寄存器UFCR的bit9:7=101, 表示1分频
47 * UBMR = 3124
48 * UBIR = 71
49 * 因此波特率= 80000000/(16 * (3124+1)/(71+1))= 115200
50 */
51 UART1->UFCR = 5<<7; //ref freq等于ipg_clk/1=80Mhz
52 UART1->UBIR = 71;
53 UART1->UBMR = 3124;
54
55 #if 0
56 uart_setbaudrate(UART1, 115200, 80000000); /* 设置波特率 */
57 #endif
58
59 /* 使能串口 */
60 uart_enable(UART1);
61 }
62
63 /*
64 * @description : 初始化串口1所使用的IO引脚
65 * @param : 无
66 * @return : 无
67 */
68 void uart_io_init(void)
69 {
70 /* 1、初始化IO复用
71 * UART1_RXD -> UART1_TX_DATA
72 * UART1_TXD -> UART1_RX_DATA
73 */
74 IOMUXC_SetPinMux(IOMUXC_UART1_TX_DATA_UART1_TX,
0); /* 复用为UART1_TX */
75 IOMUXC_SetPinMux(IOMUXC_UART1_RX_DATA_UART1_RX,
0); /* 复用为UART1_RX */
76
77 /* 2、配置UART1_TX_DATA、UART1_RX_DATA的IO属性
78 *bit 16:0 HYS关闭
79 *bit [15:14]: 00 默认100K下拉
80 *bit [13]: 0 keeper功能
81 *bit [12]: 1 pull/keeper使能
82 *bit [11]: 0 关闭开路输出
83 *bit [7:6]: 10 速度100Mhz
84 *bit [5:3]: 110 驱动能力R0/6
85 *bit [0]: 0 低转换率
86 */
87 IOMUXC_SetPinConfig(IOMUXC_UART1_TX_DATA_UART1_TX,0x10B0);
88 IOMUXC_SetPinConfig(IOMUXC_UART1_RX_DATA_UART1_RX,0x10B0);
89 }
90
91 /*
92 * @description : 波特率计算公式,
93 * 可以用此函数计算出指定串口对应的UFCR,
94 * UBIR和UBMR这三个寄存器的值
95 * @param - base : 要计算的串口。
96 * @param - baudrate : 要使用的波特率。
97 * @param - srcclock_hz :串口时钟源频率,单位Hz
98 * @return : 无
99 */
100 void uart_setbaudrate(UART_Type *base, unsigned int baudrate, unsigned int srcclock_hz)
101 {
102 uint32_t numerator = 0u;
103 uint32_t denominator = 0U;
104 uint32_t divisor = 0U;
105 uint32_t refFreqDiv = 0U;
106 uint32_t divider = 1U;
107 uint64_t baudDiff = 0U;
108 uint64_t tempNumerator = 0U;
109 uint32_t tempDenominator = 0u;
110
111 /* get the approximately maximum divisor */
112 numerator = srcclock_hz;
113 denominator = baudrate << 4;
114 divisor = 1;
115
116 while (denominator != 0)
117 {
118 divisor = denominator;
119 denominator = numerator % denominator;
120 numerator = divisor;
121 }
122
123 numerator = srcclock_hz / divisor;
124 denominator = (baudrate << 4) / divisor;
125
126 /* numerator ranges from 1 ~ 7 * 64k */
127 /* denominator ranges from 1 ~ 64k */
128 if ((numerator > (UART_UBIR_INC_MASK * 7))
129 || (denominator > UART_UBIR_INC_MASK))
130 {
131 uint32_t m = (numerator - 1) / (UART_UBIR_INC_MASK * 7) + 1;
132 uint32_t n = (denominator - 1) / UART_UBIR_INC_MASK + 1;
133 uint32_t max = m > n ? m : n;
134 numerator /= max;
135 denominator /= max;
136 if (0 == numerator)
137 {
138 numerator = 1;
139 }
140 if (0 == denominator)
141 {
142 denominator = 1;
143 }
144 }
145 divider = (numerator - 1) / UART_UBIR_INC_MASK + 1;
146
147 switch (divider)
148 {
149 case 1:
150 refFreqDiv = 0x05;
151 break;
152 case 2:
153 refFreqDiv = 0x04;
154 break;
155 case 3:
156 refFreqDiv = 0x03;
157 break;
158 case 4:
159 refFreqDiv = 0x02;
160 break;
161 case 5:
162 refFreqDiv = 0x01;
163 break;
164 case 6:
165 refFreqDiv = 0x00;
166 break;
167 case 7:
168 refFreqDiv = 0x06;
169 break;
170 default:
171 refFreqDiv = 0x05;
172 break;
173 }
174 /* Compare the difference between baudRate_Bps and calculated baud rate.
175 * Baud Rate = Ref Freq / (16 * (UBMR + 1)/(UBIR+1)).
176 * baudDiff = (srcClock_Hz/divider)/( 16 * ((numerator / divider)/ denominator).
177 */
178 tempNumerator = srcclock_hz;
179 tempDenominator = (numerator << 4);
180 divisor = 1;
181 /* get the approximately maximum divisor */
182 while (tempDenominator != 0)
183 {
184 divisor = tempDenominator;
185 tempDenominator = tempNumerator % tempDenominator;
186 tempNumerator = divisor;
187 }
188 tempNumerator = srcclock_hz / divisor;
189 tempDenominator = (numerator << 4) / divisor;
190 baudDiff = (tempNumerator * denominator) / tempDenominator;
191 baudDiff = (baudDiff >= baudrate) ? (baudDiff - baudrate) : (baudrate - baudDiff);
192
193 if (baudDiff < (baudrate / 100) * 3)
194 {
195 base->UFCR &= ~UART_UFCR_RFDIV_MASK;
196 base->UFCR |= UART_UFCR_RFDIV(refFreqDiv);
197 base->UBIR = UART_UBIR_INC(denominator - 1); //要先写UBIR寄存器,然后在写UBMR寄存器
198 base->UBMR = UART_UBMR_MOD(numerator / divider - 1);
199 }
200 }
201
202 /*
203 * @description : 关闭指定的UART
204 * @param - base: 要关闭的UART
205 * @return : 无
206 */
207 void uart_disable(UART_Type *base)
208 {
209 base->UCR1 &= ~(1<<0);
210 }
211
212 /*
213 * @description : 打开指定的UART
214 * @param - base: 要打开的UART
215 * @return : 无
216 */
217 void uart_enable(UART_Type *base)
218 {
219 base->UCR1 |= (1<<0);
220 }
221
222 /*
223 * @description : 复位指定的UART
224 * @param - base: 要复位的UART
225 * @return : 无
226 */
227 void uart_softreset(UART_Type *base)
228 {
229 base->UCR2 &= ~(1<<0); /* UCR2的bit0为0,复位UART */
230 while((base->UCR2 & 0x1) == 0); /* 等待复位完成 */
231 }
232
233 /*
234 * @description : 发送一个字符
235 * @param - c : 要发送的字符
236 * @return : 无
237 */
238 void putc(unsigned char c)
239 {
240 while(((UART1->USR2 >> 3) &0X01) == 0);/* 等待上一次发送完成 */
241 UART1->UTXD = c & 0XFF; /* 发送数据 */
242 }
243
244 /*
245 * @description : 发送一个字符串
246 * @param - str : 要发送的字符串
247 * @return : 无
248 */
249 void puts(char *str)
250 {
251 char *p = str;
252
253 while(*p)
254 putc(*p++);
255 }
256
257 /*
258 * @description : 接收一个字符
259 * @param : 无
260 * @return : 接收到的字符
261 */
262 unsigned char getc(void)
263 {
264 while((UART1->USR2 & 0x1) == 0);/* 等待接收完成 */
265 return UART1->URXD; /* 返回接收到的数据 */
266 }
267
268 /*
269 * @description : 防止编译器报错
270 * @param : 无
271 * @return : 无
272 */
273 void raise(int sig_nr)
274 {
275
276 }
Uart_init函数是UART1的初始化函数,主要设置串口的字长,停止位,校验,波特率
uart_io_init函数主要完成IO的复用功能,IO复用为串口功能。
uart_setbaudrate函数,串口波特率设置函数,该函数有三个参数,第一个是要设置的串口,第二个是波特率,第三个是串口时钟源频率。
uart_disable函数用于关闭指定的串口。
uart_enable函数用于使能指定的串口。
uart_softreset函数用于软件复位指定的串口。
putc函数用于发送一个字符。
puts函数用于发送一个字符串。
Getc函数用于接收一个字符。
然后我们打开main.c,在里面输入下面的内容:
1 #include "clk.h"
2 #include "delay.h"
3 #include "led.h"
4 #include "beep.h"
5 #include "key.h"
6 #include "int.h"
7 #include "uart.h"
8
9 /*
10 * @description : main函数
11 * @param : 无
12 * @return : 无
13 */
14 int main(void)
15 {
16 unsigned char a=0;
17 unsigned char state = OFF;
18
19 int_init(); /* 初始化中断(一定要最先调用!) */
20 imx6u_clkinit(); /* 初始化系统时钟 */
21 delay_init(); /* 初始化延时 */
22 clk_enable(); /* 使能所有的时钟 */
23 led_init(); /* 初始化led */
24 beep_init(); /* 初始化beep */
25 uart_init(); /* 初始化串口,波特率115200 */
26
27 while(1)
28 {
29 puts("请输入1个字符:");
30 a=getc();
31 putc(a); //回显功能
32 puts("\r\n");
33
34 //显示输入的字符
35 puts("您输入的字符为:");
36 putc(a);
37 puts("\r\n\r\n");
38
39 state = !state;
40 led_switch(LED0,state);
41 }
42 return 0;
43 }
在main.c中第25行调用uart_init函数,初始化UART1,最后在While(1)循环中调用getc函数获取串口收到的数据,然后调用putc把接收到的数据在通过串口发送出去,同时调用puts函数发送回车换行字符串(\r\n)。