【裸机程序】imx 6ULL串口接收信号控制LED灯
一、创作灵感学习完串口之后为了和之前学习的led灯的例子穿起来我设计了一个超级简单的串口接受信号控制led灯的例子。毕竟学习新知识多动手是王道。二、LED灯的GPIO口的初始化这个例子中GPIO1 的IO03与LED灯相连。在恩智浦提供的库当中IO口初始化主要涉及到两个函数一个是IOMUXC_SetPinMux用于选择引脚的复用功能还有一个是IOMUXC_SetPinConfig用于配置引脚的电气属性。此外GPIOx-GDIR用于配置GPIO的输入输出方向GPIOx-DR用于配置输出的电平。void led_init(void) { /* 1、初始化IO复用 */ IOMUXC_SetPinMux(IOMUXC_GPIO1_IO03_GPIO1_IO03,0); /* 复用为GPIO1_IO03 */ /* 2、、配置GPIO1_IO03的IO属性 *bit 16:0 HYS关闭 *bit [15:14]: 00 默认下拉 *bit [13]: 0 kepper功能 *bit [12]: 1 pull/keeper使能 *bit [11]: 0 关闭开路输出 *bit [7:6]: 10 速度100Mhz *bit [5:3]: 110 R0/6驱动能力 *bit [0]: 0 低转换率 */ IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO03_GPIO1_IO03,0X10B0); /* 3、初始化GPIO,GPIO1_IO03设置为输出*/ GPIO1-GDIR | (1 3); /* 4、设置GPIO1_IO03输出低电平打开LED0*/ GPIO1-DR ~(1 3); } void led_switch(int led, int status) { switch(led) { case LED0: if(status ON) GPIO1-DR ~(13); /* 打开LED0 */ else if(status OFF) GPIO1-DR | (13); /* 关闭LED0 */ break; } }三、串口的初始化与stm32类似串口的初始化同样分为2部分一部分是相关IO口的设置另一部分是串口收发属性的设置比如波特率、起始位、停止位等属性的设置。#include bsp_uart.h /* * description : 初始化串口1,波特率为115200 * param : 无 * return : 无 */ void uart_init(void) { /* 1、初始化串口IO */ uart_io_init(); /* 2、初始化UART1 */ uart_disable(UART1); /* 先关闭UART1 */ uart_softreset(UART1); /* 软件复位UART1 */ UART1- UCR1 0; /* 先清除UCR1寄存器 */ /* * 设置UART的UCR1寄存器关闭自动波特率 * bit14: 0 关闭自动波特率检测,我们自己设置波特率 */ UART1-UCR1 ~(114); /* * 设置UART的UCR2寄存器设置内容包括字长停止位校验模式关闭RTS硬件流控 * bit14: 1 忽略RTS引脚 * bit8: 0 关闭奇偶校验 * bit6: 0 1位停止位 * bit5: 1 8位数据位 * bit2: 1 打开发送 * bit1: 1 打开接收 */ UART1-UCR2 | (114) | (15) | (12) | (11); /* * UART1的UCR3寄存器 * bit2: 1 必须设置为1参考IMX6ULL参考手册3624页 */ UART1-UCR3 | 12; /* * 设置波特率 * 波特率计算公式:Baud Rate Ref Freq / (16 * (UBMR 1)/(UBIR1)) * 如果要设置波特率为115200那么可以使用如下参数: * Ref Freq 80M 也就是寄存器UFCR的bit9:7101, 表示1分频 * UBMR 3124 * UBIR 71 * 因此波特率 80000000/(16 * (31241)/(711))80000000/(16 * 3125/72) (80000000*72) / (16*3125) 115200 */ UART1-UFCR 57; //ref freq等于ipg_clk/180Mhz UART1-UBIR 71; UART1-UBMR 3124; #if 0 uart_setbaudrate(UART1, 115200, 80000000); /* 设置波特率 */ #endif /* 使能串口 */ uart_enable(UART1); } /* * description : 初始化串口1所使用的IO引脚 * param : 无 * return : 无 */ void uart_io_init(void) { /* 1、初始化IO复用 * UART1_RXD - UART1_TX_DATA * UART1_TXD - UART1_RX_DATA */ IOMUXC_SetPinMux(IOMUXC_UART1_TX_DATA_UART1_TX,0); /* 复用为UART1_TX */ IOMUXC_SetPinMux(IOMUXC_UART1_RX_DATA_UART1_RX,0); /* 复用为UART1_RX */ /* 2、配置UART1_TX_DATA、UART1_RX_DATA的IO属性 *bit 16:0 HYS关闭 *bit [15:14]: 00 默认100K下拉 *bit [13]: 0 keeper功能 *bit [12]: 1 pull/keeper使能 *bit [11]: 0 关闭开路输出 *bit [7:6]: 10 速度100Mhz *bit [5:3]: 110 驱动能力R0/6 *bit [0]: 0 低转换率 */ IOMUXC_SetPinConfig(IOMUXC_UART1_TX_DATA_UART1_TX,0x10B0); IOMUXC_SetPinConfig(IOMUXC_UART1_RX_DATA_UART1_RX,0x10B0); } /* * description : 波特率计算公式 * 可以用此函数计算出指定串口对应的UFCR * UBIR和UBMR这三个寄存器的值 * param - base : 要计算的串口。 * param - baudrate : 要使用的波特率。 * param - srcclock_hz :串口时钟源频率单位Hz * return : 无 */ void uart_setbaudrate(UART_Type *base, unsigned int baudrate, unsigned int srcclock_hz) { uint32_t numerator 0u; //分子 uint32_t denominator 0U; //分母 uint32_t divisor 0U; uint32_t refFreqDiv 0U; uint32_t divider 1U; uint64_t baudDiff 0U; uint64_t tempNumerator 0U; uint32_t tempDenominator 0u; /* get the approximately maximum divisor */ numerator srcclock_hz; denominator baudrate 4; divisor 1; while (denominator ! 0) { divisor denominator; denominator numerator % denominator; numerator divisor; } numerator srcclock_hz / divisor; denominator (baudrate 4) / divisor; /* numerator ranges from 1 ~ 7 * 64k */ /* denominator ranges from 1 ~ 64k */ if ((numerator (UART_UBIR_INC_MASK * 7)) || (denominator UART_UBIR_INC_MASK)) { uint32_t m (numerator - 1) / (UART_UBIR_INC_MASK * 7) 1; uint32_t n (denominator - 1) / UART_UBIR_INC_MASK 1; uint32_t max m n ? m : n; numerator / max; denominator / max; if (0 numerator) { numerator 1; } if (0 denominator) { denominator 1; } } divider (numerator - 1) / UART_UBIR_INC_MASK 1; switch (divider) { case 1: refFreqDiv 0x05; break; case 2: refFreqDiv 0x04; break; case 3: refFreqDiv 0x03; break; case 4: refFreqDiv 0x02; break; case 5: refFreqDiv 0x01; break; case 6: refFreqDiv 0x00; break; case 7: refFreqDiv 0x06; break; default: refFreqDiv 0x05; break; } /* Compare the difference between baudRate_Bps and calculated baud rate. * Baud Rate Ref Freq / (16 * (UBMR 1)/(UBIR1)). * baudDiff (srcClock_Hz/divider)/( 16 * ((numerator / divider)/ denominator). */ tempNumerator srcclock_hz; tempDenominator (numerator 4); divisor 1; /* get the approximately maximum divisor */ while (tempDenominator ! 0) { divisor tempDenominator; tempDenominator tempNumerator % tempDenominator; tempNumerator divisor; } tempNumerator srcclock_hz / divisor; tempDenominator (numerator 4) / divisor; baudDiff (tempNumerator * denominator) / tempDenominator; baudDiff (baudDiff baudrate) ? (baudDiff - baudrate) : (baudrate - baudDiff); if (baudDiff (baudrate / 100) * 3) { base-UFCR ~UART_UFCR_RFDIV_MASK; base-UFCR | UART_UFCR_RFDIV(refFreqDiv); base-UBIR UART_UBIR_INC(denominator - 1); //要先写UBIR寄存器然后在写UBMR寄存器3592页 base-UBMR UART_UBMR_MOD(numerator / divider - 1); } } /* * description : 关闭指定的UART * param - base: 要关闭的UART * return : 无 */ void uart_disable(UART_Type *base) { base-UCR1 ~(10); } /* * description : 打开指定的UART * param - base: 要打开的UART * return : 无 */ void uart_enable(UART_Type *base) { base-UCR1 | (10); } /* * description : 复位指定的UART * param - base: 要复位的UART * return : 无 */ void uart_softreset(UART_Type *base) { base-UCR2 ~(10); /* UCR2的bit0为0复位UART */ while((base-UCR2 0x1) 0); /* 等待复位完成 */ } /* * description : 发送一个字符 * param - c : 要发送的字符 * return : 无 */ void putc(unsigned char c) { while(((UART1-USR2 3) 0X01) 0);/* 等待上一次发送完成 */ UART1-UTXD c 0XFF; /* 发送数据 */ } /* * description : 发送一个字符串 * param - str : 要发送的字符串 * return : 无 */ void puts(char *str) { char *p str; while(*p) putc(*p); } /* * description : 接收一个字符 * param : 无 * return : 接收到的字符 */ unsigned char getc(void) { while((UART1-USR2 0x1) 0);/* 等待接收完成 */ return UART1-URXD; /* 返回接收到的数据 */ }在main函数中调用如下int main(void) { unsigned char a0; unsigned char state OFF; imx6u_clkinit(); /* 初始化系统时钟 */ clk_enable(); /* 使能所有的时钟 */ led_init(); /* 初始化led */ uart_init(); /* 初始化串口波特率115200 */ while(1) { puts(请输入1个字符:); agetc(); if(a0) { led_switch(LED0,OFF); puts(灯已打开\r\n); } if(a1) { led_switch(LED0,ON); puts(灯已关闭\r\n); } } return 0; }四、实验现象通过SecurityCRT连接串口分别输入‘0’和1,可以观察到如下现象LED灯打开效果LED灯关闭效果