tag 标签: uart

相关帖子
相关博文
  • 2024-12-10 14:03
    129 次阅读|
    0 个评论
    【萤火工场CEM5826-M11测评】OLED显示雷达数据
    【萤火工场CEM5826-M11测评】OLED显示雷达数据 本文结合之前关于串口打印雷达监测数据的研究,进一步扩展至 OLED 屏幕显示。 该项目整体分为两部分: 一、框架显示; 二、数据采集与填充显示。 为了减小 MCU 负担,采用 局部刷新 的方案。 1. 显示框架 所需库函数 Wire.h 、 Adafruit_GFX.h 、 Adafruit_SSD1306.h . 代码 #include #include #include #include "logo_128x64.h" #include "logo_95x32.h" ​ #define OLED_RESET 4 Adafruit_SSD1306display(128, 64, &Wire, OLED_RESET); ​ voidsetup() { Serial.begin(115200); display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3C (for the 128x64) display.clearDisplay(); // 清屏 display.drawBitmap(0, 0, logo, 128, 64, 1); //画出字符对应点阵数据 display.display(); delay(1000); display.clearDisplay(); /*-------------------- Display picture and text ---------------------------*/ display.drawBitmap(16, 0, logo_small, 95, 32, 1); display.setTextColor(WHITE); //设置字体颜色 display.setTextSize(2); //设置字体大小 1 is default 6x8, 2 is 12x16, 3 is 18x24 display.setCursor(0,33); //设置起始光标 display.print("v="); display.setCursor(72,33); //设置起始光标 display.print("km/h"); display.setCursor(0,49); //设置起始光标 display.print("str="); display.display(); } ​ voidloop() { } 效果 2. 显示数据 目标:实现雷达监测数据的对应填充显示,包括速度 v 和信号强度 str 代码 思路:将之前帖子中实现的串口打印数据与 OLED 显示框架结合,将 v 和 str 两数据分别填充至 OLED 屏预留位置处即可。 #include #include #include #include "logo_128x64.h" #include "logo_95x32.h" ​ #define OLED_RESET 4 Adafruit_SSD1306display(128, 64, &Wire, OLED_RESET); ​ Stringcomdata=""; ​ voidsetup() { Serial.begin(115200); =0){}//clear serialbuffer display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3C (for the 128x64) display.clearDisplay(); // 清屏 display.drawBitmap(0, 0, logo, 128, 64, 1); //画出字符对应点阵数据 display.display(); delay(1000); display.clearDisplay(); /*-------------------- Display picture and text ---------------------------*/ display.drawBitmap(16, 0, logo_small, 95, 32, 1); display.setTextColor(WHITE); //设置字体颜色 display.setTextSize(2); //设置字体大小 1 is default 6x8, 2 is 12x16, 3 is 18x24 display.setCursor(0,33); //设置起始光标 display.print("v="); display.setCursor(80,33); //设置起始光标 display.print("km/h"); display.setCursor(0,49); //设置起始光标 display.print("str="); display.display(); } ​ voidloop() { 0) { chardata=Serial.read(); comdata+=data; if (data=='\n') {// type of comdata: v=1.0 km/h, str=10151 intseparatorIndex=comdata.indexOf(','); // 假设分隔符为逗号 if (separatorIndex!=-1) { Stringpart1=comdata.substring(0, separatorIndex); // 第一个部分 Stringpart2=comdata.substring(separatorIndex+1); // 第二个部分 // 打印分割后的数据 //Serial.println(part1); // type of part1: v=1.0 km/h //Serial.println(part2); // type of part2: str=10151 /*------------ part1 : v=1.0 km/h ----------*/ intpart1separatorIndex=part1.indexOf('='); //index of '=' if (part1separatorIndex!=-1) { Stringvlc=part1.substring(part1separatorIndex+1); // index of velocity, type of vlc is 1.0 km/h // vlc: 1.0 km/h intVLCseparatorIndex=vlc.indexOf(' '); // index of ' ' Stringv=vlc.substring(0, VLCseparatorIndex);// v only include number floatVn=v.toFloat(); Serial.print(Vn); // print velocity number Serial.print(','); //display.setCursor(25,33); //设置起始光标 display.fillRect(25, 33, 60, 16, BLACK); display.display(); display.setCursor(25,33); //设置起始光标 display.print(Vn); display.display(); } /*------------- part2 : str=10151 ------------------*/ intpart2separatorIndex=part2.indexOf('='); //index of '=' if (part2separatorIndex!=-1) { Stringstrng=part2.substring(part2separatorIndex+1); // strng only include number intSn=strng.toInt(); Serial.print(Sn); // print strength number Serial.println(); //display.setCursor(49,49); //设置起始光标 display.fillRect(49, 49, 79, 16, BLACK); //display.setPixelColor(); display.display(); display.setCursor(49,49); //设置起始光标 display.print(Sn); display.display(); } } comdata=""; } } } 效果 这里由于字体设置为 2 号,无法满足 km/h 单位的完整填充,因此被数据覆盖住一部分,可根据实际需求调整字体大小。 同时支持串口绘图和串口数据打印。
  • 热度 3
    2024-3-8 11:37
    799 次阅读|
    1 个评论
    B y Toradex 胡珊逢 简介 Verdin iMX8M Plus 具有四个串口,其中 UART3 是用于 A53 核心上的系统如 Linux 的默认调试串口,出于设计需要可能需要将调试口换到其他串口,文章将介绍如何使用 UART1 作调试串口。 硬件介绍 Verdin iMX8M Plus 的四个串口 UART1 ~ UART4 中, UART3 为默认的 A53 调试串口, UART4 为 M7 调试串口,其余两个作为通用 UART 使用。 Verdin 系列的模块均使用 1.8V TTL 电平,在连接外部设备时请先检查电压。本次测试使用的是 Dahlia 底板,在 X20 扩展接口 Pin12 和 Pin13 分别将模块的 UART1_RXD 和 UART1_TXD 引出。四个串口的物理地址如下: UART 起始地址 结束地址 UART1 0x3086_0000 0x3086_FFFF UART2 0x3089_0000 0x3089_FFFF UART3 0x3088_0000 0x3088_FFFF UART4 0x30A6_0000 0x30A6_FFFF 软件修改 调试串口更改的软件涉及到三个部分, ATF 、 U-Boot 和 Linux 。 ATF 会和 U-Boot 等其他文件如 DDR 固件一起打包成用于 NXP i.MX 8M Plus 处理器的启动文件。这些文件的下载和编译请参考 该网页 。文章使用到的完整补丁请从 这里下载 。 ATF ATF 代码的 imx8mp_bl31_setup.c 中,把 RDC_PDAP_UART1 划分到 A53 所在的 D0 域。 --------------------------- --- a/plat/imx/imx8m/imx8mp/imx8mp_bl31_setup.c +++ b/plat/imx/imx8m/imx8mp/imx8mp_bl31_setup.c @@ -53,7 +53,7 @@ static const struct imx_rdc_cfg rdc = { - MX8MP_PAD_UART3_RXD__UART3_DCE_RX | MUX_PAD_CTRL(UART_PAD_CTRL), - MX8MP_PAD_UART3_TXD__UART3_DCE_TX | MUX_PAD_CTRL(UART_PAD_CTRL), + MX8MP_PAD_UART1_RXD__UART1_DCE_RX | MUX_PAD_CTRL(UART_PAD_CTRL), + MX8MP_PAD_UART1_TXD__UART1_DCE_TX | MUX_PAD_CTRL(UART_PAD_CTRL), }; imx_iomux_v3_setup_multiple_pads(uart_pads, ARRAY_SIZE(uart_pads)); - init_uart_clk(2); + init_uart_clk(0); return 0; } --------------------------- 在 include/configs/verdin-imx8mp.h 将 CONFIG_MXC_UART_BASE 的地址也设置为 UART1 。同时修改 console 。 --------------------------- --- a/include/configs/verdin-imx8mp.h +++ b/include/configs/verdin-imx8mp.h "boot_script_dhcp=" BOOT_SCRIPT "\0" \ - "console=ttymxc2\0" \ + "console=ttymxc0\0" \ "fdt_board=dev\0" \ @@ -111,7 +111,7 @@ #define PHYS_SDRAM_2_SIZE (SZ_4G + SZ_1G) /* UART */ -#define CONFIG_MXC_UART_BASE UART3_BASE_ADDR +#define CONFIG_MXC_UART_BASE UART1_BASE_ADDR /* Monitor Command Prompt */ #define CONFIG_SYS_CBSIZE SZ_2K --------------------------- Linux Linux 的 device tree 同样也需要做修改。在 freescale/imx8mp-verdin-dev.dtsi 中取消 UART1 默认配置下的 RS485 功能。 --------------------------- --- a/arch/arm64/boot/dts/freescale/imx8mp-verdin-dev.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mp-verdin-dev.dtsi /* Verdin UART_1, connector X50 through RS485 transceiver */ &uart1 { + /* linux,rs485-enabled-at-boot-time; rs485-rts-active-low; rs485-rx-during-tx; + */ status = "okay"; }; --------------------------- imx8mp-verdin.dtsi 中更改 stdout-path 调试串口输出至 UART1 ,并删除 RTS 和 CTS 功能引脚。 --------------------------- --- a/arch/arm64/boot/dts/freescale/imx8mp-verdin.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mp-verdin.dtsi @@ -8,7 +8,7 @@ / { chosen { - stdout-path = &uart3; + stdout-path = &uart1; }; aliases { @@ -891,7 +891,7 @@ &snvs_pwrkey { &uart1 { pinctrl-names = "default"; pinctrl-0 = ; - uart-has-rtscts; + /* uart-has-rtscts; */ }; /* Verdin UART_2 */ @@ -1331,8 +1331,8 @@ pinctrl_sai3: sai3grp { pinctrl_uart1: uart1grp { fsl,pins = - , /* SODIMM 135 */ - , /* SODIMM 133 */ + /* , SODIMM 135 */ + /* , SODIMM 133 */ --------------------------- 修改完毕上述文件后重新编译 flash.bin ( imx-boot )和 device tree 文件,并将其放入支持 Toradex Easy Installer 烧录的镜像文件中。同时也需要修改镜像文件中的 u-boot-initial-env-sd ,将 console 改为 console=ttymxc0 。该文件会在烧录系统时配置 U-Boot 环境变量。安装完镜像后,在 UART1 即可看到启动日志。 总结 通过上述几个文件的修改,可以切换 A53 调试串口。对于 Linux 系统通常建议保留一个调试串口,这将有利于调试和后期其他问题排查。
  • 热度 9
    2022-11-4 00:11
    2021 次阅读|
    0 个评论
    一:第一感受: 优点:板子小巧,功能强大,做工优良 不足:没有led指示灯,有led灯的话调试会方便很多 二:工程环境搭建 直接参考官网资料,很容易就搭建好了工程环境,测试ok,不得不说资料很详细。 三:IO口测试 直接用官方例程进行测试: 由于没有指示灯,所以直接用万用表进行功能测试 1:执行指令 GPIO_SET_OUTPUT_PIN_INV(gpio_sel,(GPIO_PIN7)); 量PA7脚电压为1.6V 2:执行指令 GPIO_SET_OUTPUT_PIN_TO_1(gpio_sel,(GPIO_PIN7)); 量PA7脚电压为3.2V 3:执行指令 GPIO_SET_OUTPUT_PIN_TO_0(gpio_sel,(GPIO_PIN7)); 量PA7脚电压为0V 三:串口功能测试 同样直接用官方例程进行测试不用做任何修改:接串口4到usb转串口模块上:直接测试收发如下: 四:串口printf功能移植 参考大神的方法:链接如下: 五:HAL库移植测试 参考游乐场大神的程序,链接如下: 最开始测试,串口波特率不对,修改如下图所示分频后解决 然后还遇到的问题是打印中文信息乱码,如下图所示: 经过咨询大神,发现是编码不一致导致,HAL库中使用的是UTF8字符编码,修改后OK如下图所示: 目前移植的程序还存在申请锁超时问题,待进一步解决。 总结:MC3172单片机上手容易,多线程操作给力,串口丰富可以任意分配功能强大。
  • 热度 4
    2022-5-20 07:14
    2100 次阅读|
    2 个评论
    UART介绍 简介 通用异步收发器(Universal Asynchronous Receiver/Transmitter),既UART 时序 根据时序图可以了解到: 1. uart在空闲的时候是高电平 2. 当突变为低电平或者有一个下降沿,则是告知接收方uart要传数据了 3. 这里实现为8bit数据传输,当数据传输完成,在1或1.5或2个时钟周期内将传输线拉高,表示停止传输 UART之RX实现 状态转移图 源代码 状态转移实现 always @(*) begin case (state) IDLE:begin if(rx_pin==1'b0) nextstate <= START; else nextstate <= IDLE; end START:begin if(cycle_cnt == CYCLE_CNT_MAX-1)//当一个BIT周期后,接收数据 nextstate <= REC_BYTE; else nextstate <= START; end REC_BYTE:begin if(cycle_cnt == CYCLE_CNT_MAX-1&&bit_cnt==4'd7)//8位数据接收完成,跳转到检测停止位 nextstate <= STOP; else nextstate <= REC_BYTE; end STOP:begin if(cycle_cnt == CYCLE_CNT_MAX/2-1)//半个bit周期,检测到停止位,将接收的数据发送到其他模块 nextstate <= DATA; else nextstate <= STOP; end DATA:begin //一个时钟周期后模块进入空闲态 nextstate <= IDLE; end endcase end 时序描述 //周期计数,既系统时钟内每个BIT所需要的周期数,通过波特率可计算出最大计数值 always@(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) cycle_cnt <= 16'd0; else if(state == REC_BYTE && (cycle_cnt == CYCLE_CNT_MAX-1||nextstate != state))//只需要在开始接收数据时开始计数,所以前提条件是状态在REC_BYTE,而且如果计数值达到最大值或者在状态跳转的时候都需要将计数值清零 cycle_cnt <= 16'd0; else cycle_cnt <= cycle_cnt + 16'd1; end //位计数,以确认接收的位数 always@(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) bit_cnt <= 4'd0; else if(state == REC_BYTE) //仅在接收数据状态时进行位计数 if(cycle_cnt == CYCLE_CNT_MAX-1) bit_cnt <= bit_cnt + 4'd1; else bit_cnt <= bit_cnt; else bit_cnt <= 4'd0; end //数据接收 always@(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) rx_data_r <= 8'd0; else if(state == REC_BYTE && cycle_cnt == CYCLE_CNT_MAX/2-1) rx_data_r <= tx_pin; else rx_data_r <= rx_data_r; end //将数据传输给其他模块 always@(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) rx_data <= 8'd0; else if(state == STOP || nextstate != state) rx_data <= rx_data_r; end //接收完成标志 always@(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) rx_done <= 1'b0; else if(state == STOP ) rx_done <= 1'b1; else rx_done <= 1'b0; end UART之TX实现 实现TX就不用三段式状态机这么麻烦了,直接用序列机完全就可以了 模块使能或者说发送请求 always@(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) tx_en <= 1'b0; else if(tx_req_pos == 1'b1) tx_en <= 1'b1; else if(bit_cnt == 4'd11) tx_en <= 1'b0; else tx_en <= tx_en; end 周期计数、位计数 //周期计数,既系统时钟内每个BIT所需要的周期数,通过波特率可计算出最大计数值 always@(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) cycle_cnt <= 16'd0; else if(tx_en) if(cycle_cnt == CYCLE_CNT_MAX-1)//当模块使能时,开始计数,计数到最大值再从零开始 cycle_cnt <= 16'd0; else cycle_cnt <= cycle_cnt + 16'd1; else cycle_cnt <= 16'd0; end //位计数 always@(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) bit_cnt <= 4'd0; else if(cycle_cnt == 16'd1) //如果计数到最大值bit_cnt累加的话,那么数据发送需要多等一个bit周期 bit_cnt <= bit_cnt + 4'd1; else if(bit_cnt == 4'd11) bit_cnt <= 4'd0; else bit_cnt <= bit_cnt; end 发送数据 always@(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) tx_pin_r <= 1'b1; else case(bit_cnt) 0:tx_pin_r <= 1'b1; //这里需要避免bit_cnt=0的时候发送起始位,因为当复位的时候bit_cnt的值是零的,会在复位时就已经发出了起始位,而导致接收端的误判和发送的时序紊乱 1:tx_pin_r <= START_BIT; 2:tx_pin_r <= send_data ; 3:tx_pin_r <= send_data ; 4:tx_pin_r <= send_data ; 5:tx_pin_r <= send_data ; 6:tx_pin_r <= send_data ; 7:tx_pin_r <= send_data ; 8:tx_pin_r <= send_data ; 9:tx_pin_r <= send_data ; 10:tx_pin_r <= STOP_BIT; default: tx_pin_r <= 1'b1; end
  • 2022-5-13 14:00
    2 次阅读|
    0 个评论
    智慧灯杆是集照明、视频监控、交通管理、环境监测、通信等多功能于一体的新型信息基础设施,是构建新型智慧城市的重要载体。 5G 的普及,为智慧灯杆发展创造了新机遇,作为新一代城市信息基础设施的智慧灯杆,与“新基建”中的不少领域相关,比如 5G 基站、新能源汽车充电桩和车联网等。 智慧灯杆作为智慧城市的一个重要组成部分和重要入口,是智慧城市信息化建设天然的搭载平台。可以说在智慧城市建设中, 5G 是不可或缺的主角,而智慧杆将如同末梢神经元般存在。 智慧灯杆物联网领域技术复杂,涉及网络通信、云计算、电力、人工智能等专业种类, 内含通信、视频监控、照明、环境监测、交通、信息发布、能源、运维等多个子系统。 产品设计需考虑各系统的兼容、协同,灯杆的弹性扩展以及产品服务的升级、回退、扩容等等,整体复杂度高,专业要求高。 国内某交通信号系统供应商,计划研发一款集路灯照明控制、 LED 显示、 WiFi 热点、视频监控、广告屏、环境监测、紧急呼叫、汽车充电桩、 4G/5G 微型基站等多种功能于一体的智慧灯杆产品。 智慧灯杆是多种设备设施和技术的综合体,从功能硬件方面看,通信杆、路灯、交通监控、安防监控、环境监测 、路侧广告牌等多种主要功能设施于一身。 如此多的功能设施需要互联互通,其核心是通信控制设备,因此作为主控的核心板要求算力高,性能强,且需支持多路网口和 UART ,支持 5G 和 OpenWrt 系统。 综合评估后,飞凌推荐用户选用 FET1046A-C 核心板进行产品开发。 该核心板有丰富的接口资源,包括原生 8 路网口( 最大支持 2 路 10GbE 接口), 4 路 UART , 3 路 USB3.0 等,基于该款核心板开发的通信控制设备通过光纤接口,可以实现 4G/5G 微基站和无线高速 WiFi 覆盖。 RJ45 网口方便智慧灯杆快速接入 LED 信息发布屏、高清摄像头、 WiFi 等杆载设备。 RS485 可用于环境传感器、环境监测单元、单灯控制器等设备串口通信。 FET1046A-C 核心板搭载 4 核 ARM Cortex-A72 处理器, 1.8GHz 主频, 2GB DDR4 RAM ,数据吞吐量最高可达 2.1GT/s ,高达 45000 CoreMark 分值的性能,满足执行多种通信形式、通信速率和网络协议的需求,支持对不同智慧灯杆通信方式的选用,可实现智慧灯杆系统的一站式搭建。
相关资源