i.MX6ULL终结者串口通信例程程序设计

本实验的源码工程在开发板光盘资料的:i.MX6UL终结者光盘资料\04_裸机例程源码\12_uart 目录下。我们在Ubuntu系统下使用命令“mkdir 12_uart”建立“12_uart”文件夹,如图 1所示:
在这里插入图片描述

图 1

然后使用“cd 12_uart”命令进入到12_uart文件夹,如图 2所示:
在这里插入图片描述

图 2

然后使用命令“cp -r …/11_gpt_delay/* ./”将上一章试验中的所有内容拷贝到刚刚新建的“12_uart”里面,如图 3所示:
在这里插入图片描述

图 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)。在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_46635880/article/details/109099238