Linux-Ubuntu之串口通信
- 一,串口通信
- 1.串口通信寄存器配置
- 2.串口通信软件实现
- ①手动波特率
- ②自动波特率
- ③主函数
- 二,printf和scanf实现串口的输入显示
一,串口通信
1.串口通信寄存器配置
串口通信利用接口是这个TTL,下载程序用的是OTG,先连接OTG下载程序,然后再连接到TTL接口,利用SecureCRT观察串口通信,这个Secure就像是板子的串口显示屏,能观察发送和接收的信息。
对寄存器配置,先设置UART1的复用属性和电气属性,然后关闭串口对内部的奇偶校验、停止位、起始位以及波特率进行配置,波特率一般选择115200,最后使能串口,在主函数里面调用相应函数,实现显示。
2.串口通信软件实现
#include "dsp_uart.h"
#include "dsp_gpio.h"
#include "dsp_uart.h"
#include "dsp_gpio.h"
void uart_init(void)
{
/*初始化GPIO即UART1的复用以及电器属性*/
uart_IO_init();
/*初始化:波特率等信号*/
uart_disable(UART1); //关闭UART1
uart_soft(UART1);//复位UART1
/*配置UART1*/
UART1->UCR1 = 0;
UART1->UCR1 &= ~(1<<14);
/*UART1具体配置,数据位八位。奇偶校验无,停止位1位*/
UART1->UCR2 = 0;
UART1->UCR2 |=(1<<1)|(1<<2)|(1<<5)|(1<<14);
UART1->UCR3 |=(1<<2);
/*设置波特率 115200*/
UART1->UFCR &=~(7<<7);
UART1->UFCR = (5<<7);
UART1->UBIR = 71;
UART1->UBMR =3124;
/*使能串口*/
uart_enable(UART1);
}
/*关闭串口*/
void uart_disable(UART_Type *base)
{
base->UCR1 &= ~(1<<0);
}
/*打开串口*/
void uart_enable(UART_Type *base)
{
base->UCR1 |= (1<<0);
}
/*复位UART*/
void uart_soft(UART_Type *base)
{
base->UCR2 &= ~(1<<0);
while((base->UCR2 & 0x01)==0);
}
void uart_IO_init(void) //复用功能和电器属性
{
//TX
IOMUXC_SetPinMux(IOMUXC_UART1_TX_DATA_UART1_TX,0);//设置为复用功能
IOMUXC_SetPinConfig(IOMUXC_UART1_TX_DATA_UART1_TX,0x10b0);//电器属性
//RX
IOMUXC_SetPinMux(IOMUXC_UART1_RX_DATA_UART1_RX,0);//设置为复用功能
IOMUXC_SetPinConfig(IOMUXC_UART1_RX_DATA_UART1_RX,0x10b0);//电器属性
}
/*发送一个字符*/
void putc(unsigned char c)
{
while(((UART1->USR2 >>3)&0X01) == 0);//判断上次发送完成
UART1->UTXD = c&0xff;
}
/*接收字符*/
unsigned char getc(void)
{
while((UART1->USR2 &0X01)==0);//判断有数据可以接收
return UART1->URXD;
}
/* 发送一串字符*/
void puts(char *str)
{
char *p = str;
while(*p)
{
putc(*p++);
}
}
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)/(UBIR+1)).
* 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); //瑕佸厛鍐橴BIR瀵勫瓨鍣紝鐒跺悗鍦ㄥ啓UBMR瀵勫瓨鍣紝3592椤�
base->UBMR = UART_UBMR_MOD(numerator / divider - 1);
//base->ONEMS = UART_ONEMS_ONEMS(srcclock_hz / (1000 * divider));
}
}
void raise(int sig_nr)
{
}
①手动波特率
/*设置波特率 115200*/
UART1->UFCR &=~(7<<7);
UART1->UFCR = (5<<7);
UART1->UBIR = 71;
UART1->UBMR =3124;
②自动波特率
利用函数uart_setbaudrate进行设置,串口引入的时钟为80MHZ。
uart_setbaudrate(UART1,115200,80000000);
③主函数
int main(void)
{
unsigned char kkkk=0;
int_init();//中断初始化
imx6u_clkinit();//时钟初始化
key_init();//按键初始化
clk_enable();//时钟初始化
uart_init();//串口初始化
beep_init();//凤鸣器初始化
led_init();//led初始化
while(1)
{
led_mode(ON);
puts("请输入字符:");
kkkk=getc();
putc(kkkk);
puts("\r\n");
puts("您输入的字符为:");
putc(kkkk);
puts("\r\n");
led_mode(OFF);
}
return 0;
}
二,printf和scanf实现串口的输入显示
添加include文件夹,然后将Makefile文件进行对应修改,添加相应路径,在主函数中调用printf和scanf的stdio头文件,在软件上输入数值,实现串口的输入发送,终于感觉能进行交互了。
主函数:
#include "main.h"
#include "dsp_clk.h"
#include "dsp_led.h"
#include "dsp_delay.h"
#include "beep.h"
#include "dsp_key.h"
#include "dsp_int.h"
#include "dsp_exti.h"
#include "dsp_epit.h"
#include "dsp_uart.h"
#include "stdio.h"
int main(void)
{
int a,b;
unsigned char kkkk=0;
int_init();//中断初始化
imx6u_clkinit();//时钟初始化
key_init();//按键初始化
clk_enable();//时钟初始化
uart_init();//串口初始化
beep_init();//凤鸣器初始化
led_init();//led初始化
while(1)
{
printf("输入两个整数:\r\n");
scanf("%d %d",&a,&b);
printf("%d + %d = %d \r\n",a,b,a+b);
led_mode(!kkkk);
kkkk=!kkkk;
// led_mode(ON);
// puts("请输入字符:");
// kkkk=getc();
// putc(kkkk);
// puts("\r\n");
// puts("您输入的字符为:");
// putc(kkkk);
// puts("\r\n");
// led_mode(OFF);
}
return 0;
}
最终实现界面:
关于这个软件的安装设置:https://blog.csdn.net/qq_52089863/article/details/132722671