RS422异步串口转同步串口UART2USART_UART2SSI

基于FPGA实现RS422异步串口数据接收转同步串口数据发送,RS422 和RS485是常用串口通信标准,通常既可以工作在异步模式,但是在某些工业及自动化、嵌入式等应用领域,一些场景常通过一定的方式配置或转换将RS422异步串口转换为同步串口模式,以实现调试和接口转换功能。

一、转换原理

1.1、引入高速时钟信号

异步通信中,数据的发送和接收没有统一的时钟信号来同步,靠约定的波特率等参数实现数据传输。要将 RS422 异步串口转换为同步串口,关键是引入一个高速时钟信号,能够对接收端异步串口数据进行采样和串并转换,同时也作为发送端生成时钟信号的基准时钟,并且根据生成时钟信号进行并转串。

1.2、调整数据格

异步通信有起始位、数据位、停止位等数据格式。在转换为同步串口时,保留这些标志位,同步通信在时钟信号的控制下连续地发送数据。

二、转换方法

基于FPGA 或 CPLD实现,现场可编程门阵列(FPGA)或复杂可编程逻辑器件(CPLD)可以通过编写逻辑代码来实现 RS422 异步串口到同步串口的转换。在代码中,需要对 RS422 的异步数据进行采样和处理,提取出数据信息,并根据外部输入的时钟信号或内部生成的时钟信号,将数据按照同步的方式重新组织和输出。并轻易的扩展这些通信接口数量和调整接口通信速率。

三、设计原理

基于FPGA实现RS422异步串口数据接收转同步串口数据发送的设计原理如图1所示

图1 异步串口转同步串口设计原理

3.1基于 FPGA 设计 UART从机模块:

SSI(Synchronous Serial Interface,同步串行接口)是一种常用于工业自动化及嵌入式领域传感器和控制器之间通信的同步串行通信协议。

UART_salve.v 是一种全双工、异步通信协议,数据传输以帧为单位,每帧包含1bit起始位、8bit数据位和1bit停止位。实现UART 从机模块数据的接收和发送功能设计。

接收部分

检测起始位:监测输入信号,当检测到下降沿时,认为是起始位。

采样数据:在起始位之后,按照波特率对数据位进行采样。

停止位检测:检测停止位停止1Byte数据接收。

SSI_master.v发送部分

准备数据:将UART传来的要发送的数据加载到FIFO发送缓冲区。

发送起始位:按照同步串口波特率发送起始位。

发送数据位:按照同步串口波特率依次发送数据位。

发送停止位:按照同步串口波特率发送停止位。

PS:工程详见资源下载。

void SPI2_Init(void) { hspi2.Instance=SPI2; //SP2 hspi2.Init.Mode=SPI_MODE_MASTER; //设置SPI工作模式,设置为主模式 hspi2.Init.Direction=SPI_DIRECTION_2LINES;//设置SPI单向或者双向的数据模式:SPI设置为双线模式 hspi2.Init.DataSize=SPI_DATASIZE_8BIT; //设置SPI的数据大小:SPI发送接收8位帧结构 hspi2.Init.CLKPolarity=SPI_POLARITY_LOW; //串行同步时钟的空闲状态为高电平 hspi2.Init.CLKPhase=SPI_PHASE_1EDGE; //串行同步时钟的第二个跳变沿(上升或下降)数据被采样 hspi2.Init.NSS=SPI_NSS_HARD_INPUT; //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制 // hspi2.Init.NSSPMode=SPI_NSS_PULSE_DISABLE;//NSS信号脉冲失能 // hspi2.Init.MasterKeepIOState=SPI_MASTER_KEEP_IO_STATE_ENABLE; //SPI主模式IO状态保持使能 hspi2.Init.BaudRatePrescaler=SPI_BAUDRATEPRESCALER_4;//定义波特率预分频的值:波特率预分频值为256 hspi2.Init.FirstBit=SPI_FIRSTBIT_MSB; //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始 hspi2.Init.TIMode=SPI_TIMODE_DISABLE; //关闭TI模式 hspi2.Init.CRCCalculation=SPI_CRCCALCULATION_DISABLE;//关闭硬件CRC校验 hspi2.Init.CRCPolynomial=0; //CRC值计算的多项式 HAL_SPI_Init(&hspi2 ); __HAL_SPI_ENABLE(&hspi2 ); //使能SPI2 // SPI2_ReadWriteByte(0Xff); //启动传输 } //SPI2底层驱动,时钟使能,引脚配置 //此函数会被HAL_SPI_Init()调用 //hspi:SPI句柄 void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi) { GPIO_InitTypeDef GPIO_Initure; RCC_PeriphCLKInitTypeDef SPI2ClkInit; __HAL_RCC_GPIOB_CLK_ENABLE(); //使能GPIOF时钟 __HAL_RCC_SPI2_CLK_ENABLE(); //使能SPI2时钟 //设置SPI2的时钟源 SPI2ClkInit.PeriphClockSelection=RCC_PERIPHCLK_SPI2; //设置SPI2时钟源 SPI2ClkInit.Spi123ClockSelection=RCC_SPI123CLKSOURCE_PLL; //SPI2时钟源使用PLL1Q HAL_RCCEx_PeriphCLKConfig(&SPI2ClkInit); //PB13,14,15 GPIO_Initure.Pin=GPIO_PIN_13|GPIO_PIN_12|GPIO_PIN_15; GPIO_Initure.Mode=GPIO_MODE_AF_PP; //复用推挽输出 GPIO_Initure.Pull=GPIO_PULLUP; //上拉 GPIO_Initure.Speed=GPIO_SPEED_FREQ_VERY_HIGH; //快速 GPIO_Initure.Alternate=GPIO_AF5_SPI2; //复用为SPI2 HAL_GPIO_Init(GPIOB,&GPIO_Initure); //初始化 //PB13,14,15 GPIO_Initure.Pin=GPIO_PIN_14; GPIO_Initure.Mode=GPIO_MODE_AF_PP; //复用推挽输出 GPIO_Initure.Pull=GPIO_NOPULL; //上拉 GPIO_Initure.Speed=GPIO_SPEED_FREQ_VERY_HIGH; //快速 GPIO_Initure.Alternate=GPIO_AF5_SPI2; //复用为SPI2 HAL_GPIO_Init(GPIOB,&GPIO_Initure); //初始化 } /** **************************************************************************************************** * @file my_spi.c * @author 正点原子团队(ALIENTEK) * @version V1.0 * @date 2025-01-01 * @brief MYSPI驱动代码 * @license Copyright (c) 2020-2032, 广州市星翼电子科技有限公司 **************************************************************************************************** * @attention * * 实验平台:正点原子 ESP32-S3 开发板 * 在线视频:www.yuanzige.com * 技术论坛:www.openedv.com * 公司网址:www.alientek.com * 购买地址:openedv.taobao.com * **************************************************************************************************** */ #include "my_spi.h" // 定义日志标签 static const char *TAG = "SPI_COM_TEST"; // SPI句柄 //spi_device_handle_t spi; /* 设备句柄 */ spi_device_handle_t MY_SD_Handle = NULL; /** * @brief spi初始化 * @param 无 * @retval esp_err_t */ esp_err_t my_spi_init(void) { esp_err_t ret = ESP_OK; uart_write_bytes(USART_UX, "UART Initialization started\r\n", strlen("UART Initialization started\r\n")); uart_write_bytes(USART_UX, "Step 1: Configure SPI bus parameters\r\n", strlen("Step 1: Configure SPI bus parameters\r\n")); spi_bus_config_t buscfg = { .sclk_io_num = SPI_SCLK_PIN, /* 时钟引脚 */ .mosi_io_num = SPI_MOSI_PIN, /* 主机输出从机输入引脚 */ .miso_io_num = SPI_MISO_PIN, /* 主机输入从机输出引脚 */ .quadwp_io_num = -1, /* 用于Quad模式的WP引脚,未使用时设置为-1 */ .quadhd_io_num = -1, /* 用于Quad模式的HD引脚,未使用时设置为-1 */ .max_transfer_sz = 320 * 240 * sizeof(uint16_t), /* 最大传输大小(整屏(RGB565格式)) */ }; // uart_write_bytes(USART_UX, "Step 2: Initialize SPI bus\r\n", strlen("Step 2: Initialize SPI bus\r\n")); // ESP_ERROR_CHECK(spi_bus_initialize(MY_SPI_HOST, &buscfg, SPI_DMA_CH_AUTO)); // /* SPI驱动接口配置,SPISD卡时钟是20-25MHz */ // spi_device_interface_config_t devcfg = { // .clock_speed_hz = 20 * 1000 * 1000, /* SPI时钟 */ // .mode = 0, /* SPI模式0 */ // .spics_io_num = SD_CS_PIN, /* 片选引脚 */ // .queue_size = 7, /* 事务队列尺寸 7个 */ // }; uart_write_bytes(USART_UX, "Step 2: Configure SPI device interface\r\n", strlen("Step 2: Configure SPI device interface\r\n")); spi_slave_interface_config_t devcfg = { // .clock_speed_hz = 1000000, .mode = 0, .spics_io_num = SD_CS_PIN, .queue_size = 7, .flags = 0, .post_setup_cb = NULL, .post_trans_cb = NULL // .command_bits = 0, // .address_bits = 0, // .duty_cycle_pos = 128, // 50% duty cycle }; uart_write_bytes(USART_UX, "Step 3: Add SPI bus device\r\n", strlen("Step 3: Add SPI bus device\r\n")); /* 初始化SPI总线 */ ret = spi_slave_initialize(MY_SPI_HOST, &buscfg, &devcfg, SPI_DMA_CH_AUTO); if (ret != ESP_OK) { uart_write_bytes(USART_UX, "Error: SPI bus initialization failed!\r\n", strlen("Error: SPI bus initialization failed!\r\n")); char error_msg[50]; snprintf(error_msg, sizeof(error_msg), "Error: 0x%04X\r\n", ret); uart_write_bytes(USART_UX, error_msg, strlen(error_msg)); return ret; } uart_write_bytes(USART_UX, "SPI bus initialization successful!\r\n", strlen("SPI bus initialization successful!\r\n")); /* 添加SPI总线设备 */ // ret = spi_bus_add_device(MY_SPI_HOST, &devcfg, &MY_SD_Handle); // if (ret != ESP_OK) { // uart_write_bytes(USART_UX, "Error: Adding SPI device failed!\r\n", strlen("Error: Adding SPI device failed!\r\n")); // char error_msg[50]; // snprintf(error_msg, sizeof(error_msg), "Error: 0x%04X\r\n", ret); // uart_write_bytes(USART_UX, error_msg, strlen(error_msg)); // // 清理SPI总线 // spi_bus_free(MY_SPI_HOST); // return ret; // } // ESP_ERROR_CHECK(spi_bus_add_device(MY_SPI_HOST, &devcfg, &MY_SD_Handle)); uart_write_bytes(USART_UX, "SPI device added successfully!\r\n", strlen("SPI device added successfully!\r\n")); uart_write_bytes(USART_UX, "=== SPI initialization completed ===\r\n", strlen("=== SPI initialization completed ===\r\n")); uart_write_bytes(USART_UX, "SPI is ready to start communication\r\n", strlen("SPI is ready to start communication\r\n")); return ESP_OK; } esp_err_t spi3_send_data(uint8_t *data) { if (!MY_SD_Handle) { return ESP_FAIL; } uint8_t rx_buffer[1]; spi_transaction_t t; t.length = SPI_SEND_RECIVE_LEN; t.rxlength = SPI_SEND_RECIVE_LEN; t.tx_buffer = data; t.rx_buffer = rx_buffer; t.flags = 0; // 启动传输 esp_err_t er = spi_device_transmit(MY_SD_Handle, &t); // ESP_LOGI(TAG, "发送数据:%d", data[0]); // ESP_LOGI(TAG, "接收数据:%d", rx_buffer[0]); return er; } 这是我的配置有什么问题吗
最新发布
08-28
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值