首页 » 科学 » 「正点原子Linux连载」第六十三章Linux RS232/485/GPS驱动实验_所示_串口

「正点原子Linux连载」第六十三章Linux RS232/485/GPS驱动实验_所示_串口

南宫静远 2024-12-02 03:37:49 0

扫一扫用手机浏览

文章目录 [+]

2)摘自《正点原子I.MX6U嵌入式Linux驱动开拓指南》关注官方微旗子暗记公众年夜众号,获取更多资料:正点原子

第六十三章Linux RS232/485/GPS驱动实验

「正点原子Linux连载」第六十三章Linux RS232/485/GPS驱动实验_所示_串口 「正点原子Linux连载」第六十三章Linux RS232/485/GPS驱动实验_所示_串口 科学

串口是很常用的一个外设,在Linux下常日通过串口和其他设备或传感器进行通信,根据电平的不同,串口分为TTL和RS232。
不管是什么样的接口电平,其驱动程序都是一样的,通过外接RS485这样的芯片就可以将串口转换为RS485旗子暗记,正点原子的I.MX6U-ALPHA开拓板便是这么做的。
对付正点原子的I.MX6U-ALPHA开拓板而言, RS232、RS485以及GPS模块接口通通连接到了I.MX6U的UART3接口上,因此这些外设终极都归结为UART3的串口驱动。
本章我们就来学习一下如何驱动I.MX6U-ALPHA开拓板上的UART3串口,进而实现RS232、RS485以及GSP驱动。

「正点原子Linux连载」第六十三章Linux RS232/485/GPS驱动实验_所示_串口 「正点原子Linux连载」第六十三章Linux RS232/485/GPS驱动实验_所示_串口 科学
(图片来自网络侵删)

63.1 Linux下UART驱动框架

1、uart_driver注册与注销

同I2C、SPI一样,Linux也供应了串口驱动框架,我们只须要按照相应的串口框架编写驱动程序即可。
串口驱动没有什么主机端和设备端之分,就只有一个串口驱动,而且这个驱动也已经由NXP官方已经编写好了,我们真正要做的便是在设备树中添加所要利用的串口节点信息。
当系统启动往后串口驱动和设备匹配成功,相应的串口就会被驱动起来,天生/dev/ttymxcX(X=0….n)文件。

虽然串口驱动不须要我们去写,但是串口驱动框架我们还是须要理解的,uart_driver构造体表示UART驱动,uart_driver定义在include/linux/serial_core.h文件中,内容如下:

示例代码63.1.1 uart_driver构造体

295struct uart_driver {

296struct module owner; / 模块所属者 /

297constchar driver_name; / 驱动名字 /

298constchar dev_name; / 设备名字 /

299int major; / 主设备号 /

300int minor; / 次设备号 /

301int nr; / 设备数 /

302struct console cons; / 掌握台 /

303

304/

305 these are private; the low level driver should not

306 touch these; they should be initialised to NULL

307 /

308struct uart_state state;

309struct tty_driver tty_driver;

310};

每个串口驱动都须要定义一个uart_driver,加载驱动的时候通过uart_register_driver函数向系统注册这个uart_driver,此函数原型如下:

int uart_register_driver(struct uart_driver drv)

函数参数和返回值含义如下:

drv:要注册的uart_driver。

返回值:0,成功;负值,失落败。

注销驱动的时候也须要注销掉前面注册的uart_driver,须要用到uart_unregister_driver函数,函数原型如下:

void uart_unregister_driver(struct uart_driver drv)

函数参数和返回值含义如下:

drv:要注销的uart_driver。

返回值:无。

2、uart_port的添加与移除

uart_port表示一个详细的port,uart_port定义在include/linux/serial_core.h文件,内容如下(有省略):

示例代码63.1.2 uart_port构造体

117struct uart_port {

118 spinlock_t lock; / port lock /

119unsignedlong iobase; / in/out[bwl] /

120unsignedchar __iomem membase; / read/write[bwl] /

......

235conststruct uart_ops ops;

236unsignedint custom_divisor;

237unsignedint line; / port index /

238unsignedint minor;

239 resource_size_t mapbase; / for ioremap /

240 resource_size_t mapsize;

241struct device dev; / parent device /

......

250};

uart_port中最紧张的便是第235行的ops,ops包含了串口的详细驱动函数,这个我们稍后再看。
每个UART都有一个uart_port,那么uart_port是怎么和uart_driver结合起来的呢?这里要用到uart_add_one_port函数,函数原型如下:

int uart_add_one_port(struct uart_driver drv,

struct uart_port uport)

函数参数和返回值含义如下:

drv:此port对应的uart_driver。

uport:要添加到uart_driver中的port。

返回值:0,成功;负值,失落败。

卸载UART驱动的时候也须要将uart_port从相应的uart_driver中移除,须要用到uart_remove_one_port函数,函数原型如下:

int uart_remove_one_port(struct uart_driver drv, struct uart_port uport)

函数参数和返回值含义如下:

drv:要卸载的port所对应的uart_driver。

uport:要卸载的uart_port。

返回值:0,成功;负值,失落败。

3、uart_ops实现

在上面讲解uart_port的时候说过,uart_port中的ops成员变量很主要,由于ops包含了针对UART详细的驱动函数,Linux系统收发数据终极调用的都是ops中的函数。
ops是uart_ops类型的构造体指针变量,uart_ops定义在include/linux/serial_core.h文件中,内容如下:

示例代码63.1.3 uart_ops构造体

49struct uart_ops {

50unsignedint(tx_empty)(struct uart_port );

51void(set_mctrl)(struct uart_port ,unsignedint mctrl);

52unsignedint(get_mctrl)(struct uart_port );

53void(stop_tx)(struct uart_port );

54void(start_tx)(struct uart_port );

55void(throttle)(struct uart_port );

56void(unthrottle)(struct uart_port );

57void(send_xchar)(struct uart_port ,char ch);

58void(stop_rx)(struct uart_port );

59void(enable_ms)(struct uart_port );

60void(break_ctl)(struct uart_port ,int ctl);

61int (startup)(struct uart_port );

62void(shutdown)(struct uart_port );

63void(flush_buffer)(struct uart_port );

64void(set_termios)(struct uart_port ,struct ktermios new,

65struct ktermios old);

66void(set_ldisc)(struct uart_port ,struct ktermios );

67void(pm)(struct uart_port ,unsignedint state,

68unsignedint oldstate);

69

70/

71 Return a string describing the type of the port

72 /

73constchar(type)(struct uart_port );

74

75/

76 Release IO and memory resources used by the port.

77 This includes iounmap if necessary.

78 /

79void(release_port)(struct uart_port );

80

81/

82 Request IO and memory resources used by the port.

83 This includes iomapping the port if necessary.

84 /

85int(request_port)(struct uart_port );

86void(config_port)(struct uart_port ,int);

87int(verify_port)(struct uart_port ,struct serial_struct );

88int(ioctl)(struct uart_port ,unsignedint,unsignedlong);

89 #ifdef CONFIG_CONSOLE_POLL

90int(poll_init)(struct uart_port );

91void(poll_put_char)(struct uart_port ,unsignedchar);

92int(poll_get_char)(struct uart_port );

93 #endif

94};

UART驱动编写职员须要实现uart_ops,由于uart_ops是最底层的UART驱动接口,是实实在在的和UART寄存器打交道的。
关于uart_ops构造体中的这些函数的详细含义请参考Documentation/serial/driver这个文档。

UART驱动框架大概便是这些,接下来我们理论联系实际,看一下NXP官方的UART驱动文件是如何编写的。

63.2 I.MX6U UART驱动剖析

1、UART的platform驱动框架

打开imx6ull.dtsi文件,找到UART3对应的子节点,子节点内容如下所示:

示例代码63.2.1 uart3设备节点

1 uart3: serial@021ec000 {

2 compatible ="fsl,imx6ul-uart",

3"fsl,imx6q-uart","fsl,imx21-uart";

4 reg =<0x021ec0000x4000>;

5 interrupts =<GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;

6 clocks =<&clks IMX6UL_CLK_UART3_IPG>,

7<&clks IMX6UL_CLK_UART3_SERIAL>;

8 clock-names ="ipg","per";

9 dmas =<&sdma 2940>,<&sdma 3040>;

10 dma-names ="rx","tx";

11 status ="disabled";

12};

重点看一下第2,3行的compatible属性,这里一共有三个值:"fsl,imx6ul-uart"、"fsl,imx6q-uar"和"fsl,imx21-uart"。
在uboot源码中搜索这三个值即可找到对应的UART驱动文件,此文件为drivers/tty/serial/imx.c,在此文件中可以找到如下内容:

示例代码63.2.2 UART platform驱动框架

267staticstruct platform_device_id imx_uart_devtype[]={

268{

269.name ="imx1-uart",

270.driver_data =(kernel_ulong_t)&imx_uart_devdata[IMX1_UART],

271},{

272.name ="imx21-uart",

273.driver_data =(kernel_ulong_t)

&imx_uart_devdata[IMX21_UART],

274},{

275.name ="imx6q-uart",

276.driver_data =(kernel_ulong_t)

&imx_uart_devdata[IMX6Q_UART],

277},{

278/ sentinel /

279}

280};

281 MODULE_DEVICE_TABLE(platform, imx_uart_devtype);

282

283staticconststruct of_device_id imx_uart_dt_ids[]={

284{.compatible ="fsl,imx6q-uart",.data =

&imx_uart_devdata[IMX6Q_UART],},

285{.compatible ="fsl,imx1-uart",.data =

&imx_uart_devdata[IMX1_UART],},

286{.compatible ="fsl,imx21-uart",.data =

&imx_uart_devdata[IMX21_UART],},

287{/ sentinel /}

288};

......

2071staticstruct platform_driver serial_imx_driver ={

2072.probe = serial_imx_probe,

2073.remove = serial_imx_remove,

2074

2075.suspend = serial_imx_suspend,

2076.resume = serial_imx_resume,

2077.id_table = imx_uart_devtype,

2078.driver ={

2079.name ="imx-uart",

2080.of_match_table = imx_uart_dt_ids,

2081},

2082};

2083

2084staticint __init imx_serial_init(void)

2085{

2086int ret = uart_register_driver(&imx_reg);

2087

2088if(ret)

2089return ret;

2090

2091 ret = platform_driver_register(&serial_imx_driver);

2092if(ret !=0)

2093 uart_unregister_driver(&imx_reg);

2094

2095return ret;

2096}

2097

2098staticvoid __exit imx_serial_exit(void)

2099{

2100 platform_driver_unregister(&serial_imx_driver);

2101 uart_unregister_driver(&imx_reg);

2102}

2103

2104 module_init(imx_serial_init);

2105 module_exit(imx_serial_exit);

可以看出I.MX6U的UART实质上是一个platform驱动,第267~280行,imx_uart_devtype为传统匹配表。

第283~288行,设备树所利用的匹配表,第284行的compatible属性值为"fsl,imx6q-uart"。

第2071~2082行,platform驱动框架构造体serial_imx_driver。

第2084~2096行,驱动入口函数,第2086行调用uart_register_driver函数向Linux内核注册uart_driver,在这里便是imx_reg。

第2098~2102行,驱动出口函数,第2101行调用uart_unregister_driver函数注销掉前面注册的uart_driver,也便是imx_reg。

2、uart_driver初始化

在imx_serial_init函数中向Linux内核注册了imx_reg,imx_reg便是uart_driver类型的构造体变量,imx_reg定义如下:

示例代码63.2.3 imx_reg构造体变量

1836staticstruct uart_driver imx_reg ={

1837.owner = THIS_MODULE,

1838.driver_name = DRIVER_NAME,

1839.dev_name = DEV_NAME,

1840.major = SERIAL_IMX_MAJOR,

1841.minor = MINOR_START,

1842.nr = ARRAY_SIZE(imx_ports),

1843.cons = IMX_CONSOLE,

1844};

3、uart_port初始化与添加

当UART设备和驱动匹配成功往后serial_imx_probe函数就会实行,此函数的重点事情便是初始化uart_port,然后将其添加到对应的uart_driver中。
在看serial_imx_probe函数之前先来看一下imx_port构造体,imx_port是NXP为I.MX系列SOC定义的一个设备构造体,此构造体内部就包含了uart_port成员变量,imx_port构造体内容如下所示(有缩减):

示例代码63.2.4 imx_port构造体

216struct imx_port {

217struct uart_port port;

218struct timer_list timer;

219unsignedint old_status;

220unsignedint have_rtscts:1;

221unsignedint dte_mode:1;

222unsignedint irda_inv_rx:1;

223unsignedint irda_inv_tx:1;

224unsignedshort trcv_delay;/ transceiver delay /

......

243unsignedlong flags;

245};

第217行,uart_port成员变量port。

接下来看一下serial_imx_probe函数,函数内容如下:

示例代码63.2.5 serial_imx_probe函数

1969staticint serial_imx_probe(struct platform_device pdev)

1970{

1971struct imx_port sport;

1972void __iomem base;

1973int ret =0;

1974struct resource res;

1975int txirq, rxirq, rtsirq;

1976

1977 sport = devm_kzalloc(&pdev->dev,sizeof(sport), GFP_KERNEL);

1978if(!sport)

1979return-ENOMEM;

1980

1981 ret = serial_imx_probe_dt(sport, pdev);

1982if(ret >0)

1983 serial_imx_probe_pdata(sport, pdev);

1984elseif(ret <0)

1985return ret;

1986

1987 res = platform_get_resource(pdev, IORESOURCE_MEM,0);

1988 base = devm_ioremap_resource(&pdev->dev, res);

1989if(IS_ERR(base))

1990return PTR_ERR(base);

1991

1992 rxirq = platform_get_irq(pdev,0);

1993 txirq = platform_get_irq(pdev,1);

1994 rtsirq = platform_get_irq(pdev,2);

1995

1996 sport->port.dev =&pdev->dev;

1997 sport->port.mapbase = res->start;

1998 sport->port.membase = base;

1999 sport->port.type = PORT_IMX,

2000 sport->port.iotype = UPIO_MEM;

2001 sport->port.irq = rxirq;

2002 sport->port.fifosize =32;

2003 sport->port.ops =&imx_pops;

2004 sport->port.rs485_config = imx_rs485_config;

2005 sport->port.rs485.flags =

2006 SER_RS485_RTS_ON_SEND | SER_RS485_RX_DURING_TX;

2007 sport->port.flags = UPF_BOOT_AUTOCONF;

2008 init_timer(&sport->timer);

2009 sport->timer.function = imx_timeout;

2010 sport->timer.data =(unsignedlong)sport;

2011

2012 sport->clk_ipg = devm_clk_get(&pdev->dev,"ipg");

2013if(IS_ERR(sport->clk_ipg)){

2014 ret = PTR_ERR(sport->clk_ipg);

2015 dev_err(&pdev->dev,"failed to get ipg clk: %d\n", ret);

2016return ret;

2017}

2018

2019 sport->clk_per = devm_clk_get(&pdev->dev,"per");

2020if(IS_ERR(sport->clk_per)){

2021 ret = PTR_ERR(sport->clk_per);

2022 dev_err(&pdev->dev,"failed to get per clk: %d\n", ret);

2023return ret;

2024}

2025

2026 sport->port.uartclk = clk_get_rate(sport->clk_per);

2027if(sport->port.uartclk > IMX_MODULE_MAX_CLK_RATE){

2028 ret = clk_set_rate(sport->clk_per, IMX_MODULE_MAX_CLK_RATE);

2029if(ret <0){

2030 dev_err(&pdev->dev,"clk_set_rate() failed\n");

2031return ret;

2032}

2033}

2034 sport->port.uartclk = clk_get_rate(sport->clk_per);

2035

2036/

2037 Allocate the IRQ(s) i.MX1 has three interrupts whereas later

2038 chips only have one interrupt.

2039 /

2040if(txirq >0){

2041 ret = devm_request_irq(&pdev->dev, rxirq, imx_rxint,0,

2042 dev_name(&pdev->dev), sport);

2043if(ret)

2044return ret;

2045

2046 ret = devm_request_irq(&pdev->dev, txirq, imx_txint,0,

2047 dev_name(&pdev->dev), sport);

2048if(ret)

2049return ret;

2050}else{

2051 ret = devm_request_irq(&pdev->dev, rxirq, imx_int,0,

2052 dev_name(&pdev->dev), sport);

2053if(ret)

2054return ret;

2055}

2056

2057 imx_ports[sport->port.line]= sport;

2058

2059 platform_set_drvdata(pdev, sport);

2060

2061return uart_add_one_port(&imx_reg,&sport->port);

2062}

第1971行,定义一个imx_port类型的构造体指针变量sport。

第1977行,为sport申请内存。

第1987~1988行,从设备树中获取I.MX系列SOCUART外设寄存器首地址,对付I.MX6ULL的UART3来说便是0X021EC000。
得到寄存器首地址往后对其进行内存映射,得到对应的虚拟地址。

第1992~1994行,获取中断信息。

第1996~2034行,初始化sport,我们重点关注的便是第2003行初始化sport的port成员变量,也便是设置uart_ops为imx_pops,imx_pops便是I.MX6ULL最底层的驱动函数凑集,稍后再来看。

第2040~2055行,申请中断。

第2061行,利用uart_add_one_port向uart_driver添加uart_port,在这里便是向imx_reg添加sport->port。

4、imx_pops构造体变量

imx_pops便是uart_ops类型的构造体变量,保存了I.MX6ULL串口最底层的操作函数,imx_pops定义如下:

示例代码63.2.6 imx_pops构造体

1611staticstruct uart_ops imx_pops ={

1612.tx_empty = imx_tx_empty,

1613.set_mctrl = imx_set_mctrl,

1614.get_mctrl = imx_get_mctrl,

1615.stop_tx = imx_stop_tx,

1616.start_tx = imx_start_tx,

1617.stop_rx = imx_stop_rx,

1618.enable_ms = imx_enable_ms,

1619.break_ctl = imx_break_ctl,

1620.startup = imx_startup,

1621.shutdown = imx_shutdown,

1622.flush_buffer = imx_flush_buffer,

1623.set_termios = imx_set_termios,

1624.type = imx_type,

1625.config_port = imx_config_port,

1626.verify_port = imx_verify_port,

1627 #if defined(CONFIG_CONSOLE_POLL)

1628.poll_init = imx_poll_init,

1629.poll_get_char = imx_poll_get_char,

1630.poll_put_char = imx_poll_put_char,

1631 #endif

1632};

imx_pops中的函数基本都是和I.MX6ULL的UART寄存器打交道的,这里就不去详细的剖析了。
大略的理解了I.MX6U的UART驱动往后我们再来学习一下,如何驱动正点原子I.MX6U-ALPHA开拓板上的UART3接口。

63.3 硬件事理图剖析

本实验要用到的I.MX6U的UART3接口,I.MX6U-ALPHA开拓板上RS232、RS485和GPS这三个接口都连接到了UART3上,我们依次来看一下这三个模块的事理图。

1、RS232事理图

RS232事理图如图63.3.1所示:

图63.3.1 RS232事理图

从图63.3.1可以看出,RS232电平通过SP3232这个芯片来实现,RS232连接到了I.MX6U的UART3接口上,但是要通过JP1这个跳线帽设置。
把JP1的1-3和2-4连接起来往后SP3232就和UART3连接到了一起。

2、RS485事理图

RS485事理图如图63.3.2所示:

图63.3.2 RS485事理图

RS485采取SP3485这颗芯片来实现,RO为数据输出端,RI为数据输入端,RE是吸收使能旗子暗记(低电平有效),DE是发送使能旗子暗记(高电平有效)。
在图63.3.2中RE和DE经由一系列的电路,终极通过RS485_RX来掌握,这样我们可以省却一个RS485收发掌握IO,将RS485完备当作一个串口来利用,方便我们写驱动。

3、GPS事理图

正点原子有一款GPS+北斗定位模块,型号为ATK1218-BD,I.MX6U-ALPHA开拓板留出了这款GPS定位模块的接口,接口事理图如图63.3.3所示:

图63.3.3 ATK MODULE模块。

从图63.3.3可以看出,GPS模块用的也是UART3,因此UART3驱动成功往后就可以直接读取GPS模块数据了。

63.4 RS232驱动编写

前面我们已经说过了,I.MX6U的UART驱动NXP已经编写好了,以是不须要我们编写。
我们要做的便是在设备树中添加UART3对应的设备节点即可。
打开imx6ull-alientek-emmc.dts文件,在此文件中只有UART1对应的uart1节点,并没有UART3对应的节点,因此我们可以参考uart1节点创建uart3节点。

1、UART3IO节点创建

UART3用到了UART3_TXD和UART3_RXD这两个IO,因此要先在iomuxc中创建UART3对应的pinctrl子节点,在iomuxc中添加如下内容:

示例代码63.4.1 UART3引脚pinctrl节点

1 pinctrl_uart3: uart3grp {

2 fsl,pins =<

3 MX6UL_PAD_UART3_TX_DATA__UART3_DCE_TX 0X1b0b1

4 MX6UL_PAD_UART3_RX_DATA__UART3_DCE_RX 0X1b0b1

5>;

6};

末了检讨一下UART3_TX和UART3_RX这两个引脚有没有被用作其他功能,如果有的话要将其屏蔽掉,担保这两个IO只用作UART3,牢记!


2、添加uart3节点

默认情形下imx6ull-alientek-emmc.dts中只有uart1和uart2这两个节点,如图63.4.1所示:

图63.4.1uart1和uart2节点

uart1是UART1的,在正点原子的I.MX6U-ALPHA开拓板上没有用到UART2,而且UART2默认用到了UART3的IO,因此须要将uart2这个节点删除掉,然后加上UART3对应的uart3,uart3节点内容如下:

示例代码63.4.2 UART3对应的uart3节点

1&uart3 {

2 pinctrl-names ="default";

3 pinctrl-0=<&pinctrl_uart3>;

4 status ="okay";

5};

完成往后重新编译设备树并利用新的设备树启动Linux,如果设备树修正成功的话,系统启动往后就会天生一个名为"/dev/ttymxc2"的设备文件,ttymxc2便是UART3对应的设备文件,运用程序可以通过访问ttymxc2来实现对UART3的操作。

63.5 移植minicom

minicom类似我们常用的串口调试助手,是Linux下很常用的一个串口工具,将minicom移植到我们的开拓板中,这样我们就可以借助minicom对串口进行读写操作。

1、移植ncurses

minicom须要用到ncurses,依次须要先移植ncurses,如果前面已经移植好了ncurses,那么这里就不须要再次移植了,只须要在编译minicom的时候指定ncurses库和头文件目录即可。

首先在ubuntu中创建一个目录来存放我们要移植的文件,比如我在/home/zuozhongkai/linux/IMX6ULL目录下创建了一个名为"tool"的目录来存放所有的移植文件。
然后下载ncurses源码,我们已经将ncurses源码放到了开拓板光盘中,路径为:1、例程源码-》7、第三方库源码-》ncurses-6.0.tar.gz,将ncurses-6.0.tar.gz拷贝到Ubuntu中创建的tool目录下,然后进行解压,解压命令如下:

tar -vxzf ncurses-6.0.tar.gz

解压完成往后就会天生一个名为"ncurses-6.0"的文件夹,此文件夹便是ncureses的源码文件夹。
在tool目录下新建名为"ncurses"目录,用于保存ncurses编译结果,统统准备就绪往后就可以编译ncureses库了。
进入到ncureses源码目录下,也便是刚刚解压出来的ncurses-6.0目录中,首先是配置ncureses,输入如下命令:

./configure --prefix=/home/zuozhongkai/linux/IMX6ULL/tool/ncurses --host=arm-linux-gnueabihf --with-shared

configure便是配置脚本,--prefix用于指定编译结果的保存目录,这里肯定将编译结果保存到我们前面创建的"ncurses"目录中。
--hsot用于指定编译器前缀,这里设置为"arm-linux-gnueabihf"。
配置命令写好往后点击回车键,等待配置完成,配置成功往后如图63.5.1所示:

图63.5.1 配置成功

配置成功往后输入"make"命令开始编译,编译成功往后如图63.5.2所示:

图63.5.2 编译成功

编译成功往后输入"makeinstall"命令安装,安装的意思便是将编译出来的结果拷贝到--pfefix指定的目录里面去。
安装成功往后如图63.5.3所示:

图63.5.3 安装成功

安装成功往后查看一下前面创建的"ncurses"文件夹,会创造里面多了一些东西,如图63.5.4所示:

图63.5.4 编译出来的结果

我们须要将图63.5.4中include、lib和share这三个目录中存放的文件分别拷贝到开拓板根文件系统中的/usr/include、/usr/lib和/usr/share这三个目录中,如果哪个目录不存在的话请自行创建!

拷贝命令如下:

sudo cp lib/ /home/zuozhongkai/linux/nfs/rootfs/usr/lib/ -rfa

sudo cp share/ /home/zuozhongkai/linux/nfs/rootfs/usr/share/ -rfa

sudo cp include/ /home/zuozhongkai/linux/nfs/rootfs/usr/include/ -rfa

然后在开拓板根目录的/etc/profile(没有的话自己创建一个)文件中添加如下所示内容:

示例代码63.5.1 /etc/provile文件

1 #!/bin/sh

2 LD_LIBRARY_PATH=/lib:/usr/lib:$LD_LIBRARY_PATH

3 export LD_LIBRARY_PATH

4

5 export TERM=vt100

6 export TERMINFO=/usr/share/terminfo

2、移植minicom

连续移植minicom,获取minicom源码,我们已经放到了开拓板光盘中了,路径为:1、例程源码-》7、第三方库源码-》minicom-2.7.1.tar.gz。
将minicom-2.7.1.tar.gz拷贝到ubuntu中的/home/zuozhongkai/linux/IMX6ULL/tool目录下,然后在tool目录下新建一个名为"minicom"的子目录,用于存放minicom编译结果。
统统准备好往后就可以编译minicom了,先解压minicom,命令如下:

tar -vxzf minicom-2.7.1.tar.gz

解压完成往后会天生一个叫做minicom-2.7.1的文件夹,这个便是minicom的源码,进入到此目录中,然后配置minicom,配置命令如下:

cd minicom-2.7.1/ //进入minicom源码目录

./configure CC=arm-linux-gnueabihf-gcc --prefix=/home/zuozhongkai/linux/IMX6ULL/tool/

minicom --host=arm-linux-gnueabihf CPPFLAGS=-I/home/zuozhongkai/linux/IMX6ULL/tool/

ncurses/include LDFLAGS=-L/home/zuozhongkai/linux/IMX6ULL/tool/ncurses/lib -enable-cfg-dir=/etc/minicom //配置

CC表示要利用的gcc交叉编译器,--prefix指定编译出来的文件存放目录,肯定要存放到我们前面创建的minicom目录中。
--host指定交叉编译器前缀,CPPFLAGS指定ncurses的头文件路径,LDFLAGS指定ncurses的库路径。

配置成功的话如图63.5.5所示:

图63.5.5 配置成功

配置成功往后实行如下命令编译并安装:

make

makeinstall

编译安装完成往后,前面创建的minicom目录内容如图63.5.6所示:

图63.5.6 minicom安装编译结果

将minicom目录中bin子目录下的所有文件拷贝到开拓板根目录中的/usr/bin目录下,命令如下:

sudo cp bin/ /home/zuozhongkai/linux/nfs/rootfs/usr/bin/

完成往后在开拓板中输入"minicom-v"来查看minicom事情是否正常,结果如图63.5.7所示:

图63.5.7 minicom版本号

从图63.5.7可以看出,此时minicom版本号为2.7.1,minicom版本号查看正常。
输入如下命令打开minicom配置界面:

minicom-s

结果是打不开minicom配置界面,提示如图63.5.8所示信息:

图63.5.8 minicom打开失落败

从图63.5.8可以看出,minicom非常嚣张,竟然让我们"Goaway",这能容忍?!
必须要治一下。
办理方法很大略,新建/etc/passwd文件,然后在passwd文件里面输入如下所示内容:

示例代码63.5.2 /etc/passwd文件

1 root:x:0:0:root:/root:/bin/sh

完成往后重启开拓板!

完成往后重启开拓板!

完成往后重启开拓板!

开拓板重启往后再实行"minicom-s"命令,此时minicom配置界面就可以打开了,如图63.5.9所示:

图63.5.9 mincom配置界面

如果能涌现图63.5.9所示界面,那么就解释mincom事情正常了。

63.6 RS232驱动测试63.6.1 RS232连接设置

在测试之前要先将I.MX6U-ALPHA开拓板的RS232与电脑连接起来,首先设置JP1跳线帽,如图63.6.1.1所示:

图63.6.1.1 UART3 跳线帽设置

跳线帽设置好往后利用RS232线将开拓板与电脑连接起来,这里建议利用USB转DB9(RS232)数据线,比如正点原子售卖的CH340方案的USB转公头DB9数据线,如图63.6.1.2所示:

图63.6.1.2 USB转DB9数据线

图63.6.1.2中所示的数据线是带有CH340芯片的,因此当连接到电脑往后就会涌现一个COM口,这个COM口便是我们要利用的COM口。
比如在我的电脑上便是COM9,在SecureCRT上新建一个连接,串口为COM9,波特率为115200。

63.6.2 minicom设置

在开拓板中输入"minicom-s",打开minicom配置界面,然后选中"Serialportsetup",如图63.6.2.1所示:

图63.6.2.1 选中串口设置项

选中"Serialportsetup"往后点击回车,进入设置菜单,如图63.6.2.2所示:

图63.6.2.2 串口设置项

图63.6.2.2中有7个设置项目,分别对应A、B……G,比如第一个是选中串口,UART3的串口文件为/dev/ttymxc2,因此串口设置要设置为/dev/ttymxc2。
设置方法便是按下键盘上的'A',然后输入"/dev/ttymxc2"即可,如图63.6.2.3所示:

图63.6.2.3 串口设备文件设置

设置完往后按下回车键确认,确认完往后就可以设置其他的配置项。
比如E设置波特率、数据位和停滞位的、F设置硬件流控的,设置方法都一样,设置完往后如图63.6.2.4所示:

图63.6.2.4 UART3设置

都设置完成往后按下回车键确认并退出,这时候会退回到如图63.6.2.1所示的界面,按下ESC键退出图63.6.2.1所示的配置界面,退出往后如图63.6.2.5所示:

图63.6.2.5 minicom串口界面

图63.6.2.2便是我们的串口调试界面,可以看出当前的串口文件为/dev/ttymxc2,按下CTRL-A,然后再按下Z就可以打开minicom帮助信息界面,如图63.6.2.6所示:

图63.6.2.6 minicom帮助信息界面

从图63.6.2.6可以看出,minicom有很多快捷键,本实验我们打开minicom的回显功能,回显功能配置项为"local Echoon/off..E",因此按下E即可打开/关闭回显功能。

63.6.3 RS232收发测试

1、发送测试

首先测试开拓板通过UART3向电脑发送数据的功能,须要打开minicom的回显功能(不打开也可以,但是在minicom中看不到自己输入的内容),回显功能打开往后输入"AAAA",如图63.6.3.1所示:

图63.6.3.1 通过UART3向电脑发送"AAAA"

图63.6.3.1中的"AAAA"相称于开拓板通过UART3向电脑发送"AAAA",那么COM9就会吸收到"AAAA",SecureCRT中COM9收到的数据如图63.6.3.2所示:

图63.6.3.2 电脑吸收到开拓板发送过来的数据

可以看出,开拓板通过UART3向电脑发送数据正常,那么接下来就测试开拓板数据吸收功能。

2、吸收测试

接下来测试开拓板的UART3吸收功能,同样的,要先打开SecureCRT上COM9确当地回显,否则的话你在COM9上输出的内容会看不到,但是实际上是已经发送给了开拓板。
选中SecureCRT的Options->Session Options->Adavnced,打开回话配置界面,然后选中"Localecho",如图63.6.3.3所示:

图63.6.3.3 打开SecureCRT确当地回显

SecureCRT设置好往后向开拓板发送一个"BBBB",在SecureCRT的COM9上输入"BBBB",如图63.6.3.3所示:

图63.6.3.3 电脑向开拓板发送"BBBB"

此时开拓板的minicom就会吸收到发送过来的"BBBB",如图63.6.3.4所示:

图63.6.3.4 开拓板吸收到发送过来的数据

UART3收发测试都没有问题,解释我们的UART3驱动事情正常。
如果要退出minicom的话,在minicom通信界面按下CRTL+A,然后按下X来关闭minicom。
关于minicom的利用我们这里讲的很大略,大家可以在网上查找更加详细的minicom利用教程。

63.7 RS485测试

前面已经说过了,I.MX6U-ALPHA开拓板上的RS485接口连接到了UART3上,因此实质上便是个串口。
RS232实验我们已经将UART3的驱动编写好了,以是RS485实验就不须要编写任何驱动程序,可以直策应用minicom来进行测试。

63.7.1 RS485连接设置

首先是设置JP1跳线帽,将3-5、4-6连接起来,如图63.7.1.1所示:

图63.7.1.1 RS485接口设置

一个板子是不能进行RS485通信测试的,还须要另一个RS485设备,比如其余一块I.MX6U-ALPHA开拓板。
这里推举大家利用正点原子出品的USB三合一串口转换器,支持USB转TTL、RS232和RS485,如图63.7.1.2所示:

图63.7.1.2正点原子USB三合一串口转换器

利用杜邦线将USB串口转换器的RS485接口和I.MX6U-ALPHA开拓板的RS485连接起来,A接A,B接B,不能接错了!
连接完成往后如图63.7.1.3所示:

图63.7.1.3串口转换器和开拓板RS485连接示意图

串口转换器通过USB线连接到电脑上,我用的是CH340版本的,因此就不须要安装驱动的,如果利用的是FT232版本的就须要安装相应的驱动。
连接成功往后电脑就会有相应的COM口,比如我的电脑上便是COM10,接下来便是测试。

63.7.2 RS485收发测试

RS485的测试和RS232千篇一律!
USB多合一转换器的COM口为10,因此利用SecureCRT创建一个COM10的连接。
开拓板利用UART3,对应的串口设备文件为/dev/ttymxc2,因此开拓板利用minicom创建一个/dev/ttymxc2的串口连接。
串口波特率都选择115200,8位数据位,1位停滞位,关闭硬件和软件流控。

1、RS485发送测试

首先测试开拓板通过RS485发送数据,设置好minicom往后,同样输入"AAAA",也便是通过RS485向电脑发送一串"AAAA"。
如果RS485驱动事情正常的话,那么电脑就会先容到开拓板发送过来的"AAAA",如图63.7.2.1所示:

图63.7.2.1 RS485数据发送测试

从图63.7.2.1可以看出开拓板通过RS485向电脑发送"AAAA"成功,解释RS485数据数据发送正常。

2、RS485吸收测试

接下来测试一下RS485数据吸收,电脑通过RS485向开拓板发送"BBBB",然后不雅观察minicom是否能吸收到"BBBB"。
结果如图63.7.2.2所示:

图63.7.2.2 RS485数据吸收测试

从图63.7.2.1可以看出开拓板吸收到电脑通过RS485发送过来的"BBBB",解释RS485数据吸收也正常。

63.8 GPS测试63.8.1 GPS连接设置

GPS模块大部分都是串口输出的,这里以正点原子出品的ATK1218-BD模块为例,这是一款GSP+北斗的定位模块,模块如图63.8.1.1所示:

图63.8.1.1正点原子ATK1218-BD定位模块

首先要将I.MX6U-ALPHA开拓板上的JP1跳线帽拔掉,不能连接RS232或RS485,否则会滋扰到GSP模块。
UART3_TX和UART3_RX已经连接到了开拓板上的ATK MODULE上,直接将ATK1218-BD模块插到开拓板上的ATK MODULE接口即可,开拓板上的ATK MODULE接口是6脚的,而ATK1218-BD模块是5脚的,因此须要靠左插!
然后GPS须要接上天线,天线的吸收头一定要放到户外,因此室内一样平常是没有GPS旗子暗记的。
连接完成往后如图63.8.1.2所示:

图63.8.1.2 GPS模块连接示意图

63.8.2 GPS数据吸收测试

GPS我们都是被动吸收定位数据的,因此打开minicom,设置/dev/ttymxc2,串口设置哀求如下:

①、波特率设置为38400,由于正点原子的ATK1218-BD模块默认波特率便是38400。

②、8位数据位,1位停滞位。

③、关闭硬件和软件流控。

设置好往后如图63.8.2.1所示:

图63.8.2.1串口设置

设置好往后就可以悄悄的等待GPS数据输出,GPS模块第一次启动可能须要几分钟搜星,等搜到卫星往后才会有定位数据输出。
搜到卫星往后GPS模块输出的定位数据如图63.8.2.2所示:

图63.8.2.2 GPS数据

标签:

相关文章

2722IT,驱动未来科技发展的关键力量

随着科技的飞速发展,信息技术(IT)已成为推动社会进步的重要力量。在这个数字化时代,2722IT作为一个新兴的科技领域,正逐渐成为...

科学 2024-12-31 阅读0 评论0

黑夜禁响门铃_电路_门铃

多年前建造的小老区楼层都没有公用照明灯.也没有门铃,只好自己各装了一只。方便中也有烦恼,小区出租房多,上夜班的人多,在阴郁中弄不清...

科学 2024-12-31 阅读0 评论0

奥迪第一代液晶仪表拆解_奥迪_板子

弁言:连续来找汽车电子的硬件拆剖解析。这次是针对2014年的奥迪第一代液晶仪表,博世开拓的。这款12.3英寸屏幕(1440540...

科学 2024-12-31 阅读0 评论0