通信总线----UART(有详细代码)

UART

通用异步收发传输器(Universal Asynchronous Receiver/Transmitter),通常称作UART。它将要传输的资料在串行通信与并行通信之间加以转换。作为把并行输入信号转成串行输出信号的芯片,UART通常被集成于其他通讯接口的连结上。

本文详细文档完整的代码会在后面文章以文档的形式发出来

1. 硬件连接

硬件连接比较简单,仅需要3条线,注意连接时两个设备UART电平,如电平范围不一致请做电平转换后再连接,如下图所示:
在这里插入图片描述
TX:发送数据端,要接对面设备的RX
RX:接收数据端,要接对面设备的TX
GND:保证两设备共地,有统一的参考平面

2. 软件通信协议

在这里插入图片描述
空闲位:
UART协议规定,当总线处于空闲状态时信号线的状态为‘1’即高电平

起始位:
开始进行数据传输时发送方要先发出一个低电平’0’来表示传输字符的开始。因为空闲位一直是高电平所以开始第一次通讯时先发送一个明显区别于空闲状态的信号即为低电平。

数据位:
起始位之后就是要传输的数据,数据可以是5,6,7,8,9位,构成一个字符,一般都是8位。先发送最低位最后发送最高位。

奇偶校验位:
数据位传送完成后,要进行奇偶校验,校验位其实是调整个数,串口校验分几种方式:
1.无校验(no parity)
2.奇校验(odd parity):如果数据位中’1’的数目是偶数,则校验位为’1’,如果’1’的数目是奇数,校验位为’0’。
3.偶校验(even parity):如果数据为中’1’的数目是偶数,则校验位为’0’,如果为奇数,校验位为’1’。
4.mark parity:校验位始终为1
5.space parity:校验位始终为0

停止位:
数据结束标志,可以是1位,1.5位,2位的高电平。

波特率:
数据传输速率使用波特率来表示,单位bps(bits per second),常见的波特率9600bps,115200bps等等,其他标准的波特率是1200,2400,4800,19200,38400,57600。举个例子,如果串口波特率设置为9600bps,那么传输一个比特需要的时间是1/9600≈104.2us。

3. 发送具体模块介绍

(1)发送的框图:
在这里插入图片描述

(2)发送的状态转移图:
在这里插入图片描述
(3)时钟产生模块:
在这里插入图片描述
(4)计数器模块:
在这里插入图片描述
(5)奇偶校验模块:
在这里插入图片描述
(6)移位寄存器模块:
在这里插入图片描述

4.接收具体模块介绍:

(1)接收模块的框图:
在这里插入图片描述
(2)接收模块的状态转移图:
在这里插入图片描述

5.发送模块的代码

(1)状态机代码

module FSM(
    input       SysClk,
    input       rst_n,
    input       Send,
    input       NextBit,
    input       Count_finish,
    output reg  Busy,
    output reg  ResetTimer,
    output reg  Increment,
    output reg  ResetCounter,
    output reg  Shift,
    output reg  Load       
);

//-----------------------------------
//状态变量、状态编码(初始值为0的独热码)
//-----------------------------------           
    reg [3:0]CS,NS;//CS:当前状态;NS:下一状态
    parameter [3:0]
        IDLE  = 4'b0000,
        LOAD  = 4'b0001,
        COUNT = 4'b0010,
        SHIFT = 4'b0100,
        WAIT  = 4'b1000;

//-----------------------------------
//时序逻辑描述状态转移
//-----------------------------------   
    always @(posedge SysClk or negedge rst_n)
        if(!rst_n) CS <= IDLE;
        else CS <= NS;

//-----------------------------------
//组合逻辑判断状态转移条件,描述状态转移规律
//-----------------------------------
    always @(rst_n or CS or Send or NextBit or Count_finish)//敏感列表中为复位信号、当前状态和输入条件
        begin
            NS = 4'bx;//默认状态为不定态X
            case(CS)//敏感列表为当前状态
                IDLE:   begin
                            if(!Send)    NS = IDLE;
                            if(Send)     NS = LOAD;
                        end
                LOAD:   NS = COUNT;
                COUNT:  begin
                            if(!NextBit) NS = COUNT;
                            if(NextBit)  NS = SHIFT;
                        end
                SHIFT:  begin
                            if(!Count_finish) NS = COUNT;
                            if(Count_finish)  NS = WAIT;
                        end
                WAIT:   begin
                            if(Send)     NS = WAIT;
                            if(!Send)    NS = IDLE;
                        end 
                default: NS = IDLE;
            endcase
        end

//-----------------------------------
//时序逻辑描述每个状态的输出
//-----------------------------------
 always @(posedge SysClk or negedge rst_n)
        if(!rst_n) begin
            ResetCounter <= 1'b0;
            ResetTimer <= 1'b0;//复位信号高有效
            Load <= 1'b0;
            Shift <= 1'b0;
            Busy <= 1'b0;
            Increment <= 1'b0;
        end
        else begin
            case(NS)//敏感列表为下一状态
                IDLE:   begin
                            ResetCounter <= 1'b0;
                            ResetTimer <= 1'b0;
                            Load <= 1'b0;
                            Shift <= 1'b0;
                            Busy <= 1'b0;
                            Increment <= 1'b0;
                        end
                LOAD:   begin
                            ResetCounter <= 1'b1;
                            ResetTimer <= 1'b1;
                            Load <= 1'b1;
                            Shift <= 1'b0;
                            Busy <= 1'b1;
                            Increment <= 1'b0;
                        end
                COUNT:  begin
                            ResetCounter <= 1'b0;
                            ResetTimer <= 1'b0;
                            Load <= 1'b0;
                            Shift <= 1'b0;
                            Busy <= 1'b1;
                            Increment <= 1'b0;
                        end
                SHIFT:  begin
                            ResetCounter <= 1'b0;
                            ResetTimer <= 1'b0;
                            Load <= 1'b0;
                            Shift <= 1'b1;
                            Busy <= 1'b1;
                            Increment <= 1'b1;
                        end
                WAIT:   begin
                            ResetCounter <= 1'b0;
                            ResetTimer <= 1'b0;
                            Load <= 1'b0;
                            Shift <= 1'b0;
                            Busy <= 1'b0;
                            Increment <= 1'b0;
                        end
                default:begin
                            ResetCounter <= 1'b0;
                            ResetTimer <= 1'b0;
                            Load <= 1'b0;
                            Shift <= 1'b0;
                            Busy <= 1'b0;
                            Increment <= 1'b0;
                        end
            endcase
        end
endmodule

(2)计数器模块:

module Mod10_Counter(
    input       SysClk,
    input       ResetCounter,//高电平有效
    input       Increment,
    input [1:0] mode,
    output reg  Count_finish
);
    reg [3:0] count;
    reg [3:0] count_preload;
// 模式选择
    always @(posedge SysClk or negedge ResetCounter) begin 
        if(ResetCounter) begin
            count_preload <= 0;
        end else begin
                    case (mode)
                        0:  begin
                                count_preload <= 7;<
  • 7
    点赞
  • 59
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
RT1021-EVK是NXP公司推出的一款基于i.MX RT1021处理器的评估开发板,它支持多种通信接口,包括CAN和UART。CAN是一种面向实时应用的通信协议,而UART是一种异步串行通信协议。下面我们来分析一下如何将CAN通信转换为UART通信,并给出相应的代码示例。 在RT1021-EVK上,CAN通信和UART通信的实现都需要使用相应的外设模块。CAN通信需要使用FlexCAN模块,而UART通信需要使用UART模块。要将CAN通信转换为UART通信,需要通过中断的方式获取CAN数据帧,然后将数据帧转换为UART数据,发送到UART总线上。 下面是CAN转UART的代码示例,仅供参考: ```c #include "fsl_flexcan.h" #include "fsl_uart.h" #define CAN_MSG_BUF_NUM 9U #define CAN_MSG_BUF_SIZE sizeof(flexcan_frame_t) flexcan_handle_t flexcanHandle; flexcan_mb_transfer_t rxXfer; flexcan_frame_t rxFrame; uart_handle_t uartHandle; uint8_t uartTxBuffer[CAN_MSG_BUF_SIZE]; void FLEXCAN_UserRxCallback(CAN_Type *base, flexcan_handle_t *handle, uint32_t mbIdx, void *userData) { UART_SendDataBlocking(UART5, uartTxBuffer, CAN_MSG_BUF_SIZE); } int main(void) { flexcan_config_t flexcanConfig; flexcan_rx_mb_config_t mbConfig; uart_config_t uartConfig; uint32_t i; BOARD_InitPins(); BOARD_BootClockRUN(); BOARD_InitDebugConsole(); /* Configure the FlexCAN module */ FLEXCAN_GetDefaultConfig(&flexcanConfig); flexcanConfig.baudRate = 500000U; FLEXCAN_Init(CAN1, &flexcanConfig, CLOCK_GetFreq(kCLOCK_IpgClk)); /* Configure the FlexCAN RX message buffer */ mbConfig.format = kFLEXCAN_FrameFormatStandard; mbConfig.type = kFLEXCAN_FrameTypeData; mbConfig.id = 0x123U; FLEXCAN_SetRxMbConfig(CAN1, RX_MESSAGE_BUFFER_NUM, &mbConfig, true); /* Create the FlexCAN handle */ FLEXCAN_TransferCreateHandle(CAN1, &flexcanHandle, FLEXCAN_UserRxCallback, NULL); /* Configure the UART module */ UART_GetDefaultConfig(&uartConfig); uartConfig.baudRate_Bps = 115200U; uartConfig.enableTx = true; uartConfig.enableRx = false; UART_Init(UART5, &uartConfig, CLOCK_GetFreq(kCLOCK_IpgClk)); /* Create the UART handle */ UART_TransferCreateHandle(UART5, &uartHandle, NULL, NULL); /* Start the FlexCAN module */ FLEXCAN_Start(CAN1); while (1) { /* Wait for the FlexCAN message */ rxXfer.mbIdx = RX_MESSAGE_BUFFER_NUM; rxXfer.frame = &rxFrame; FLEXCAN_TransferReceiveNonBlocking(CAN1, &flexcanHandle, &rxXfer); /* Convert FlexCAN message to UART message */ for (i = 0; i < CAN_MSG_BUF_SIZE; i++) { uartTxBuffer[i] = ((uint8_t *)&rxFrame)[i]; } /* Send UART message */ UART_TransferSendBlocking(UART5, &uartHandle, uartTxBuffer, CAN_MSG_BUF_SIZE); } } ``` 在这个示例中,我们使用了FlexCAN模块和UART模块,其中FlexCAN用于接收CAN数据帧,UART用于发送UART数据。在主循环中,我们使用FLEXCAN_TransferReceiveNonBlocking函数从FlexCAN模块中接收CAN数据帧,并将其转换为UART数据,然后使用UART_TransferSendBlocking函数将UART数据发送到UART总线上。同时,在CAN数据帧接收完成后,我们通过中断的方式调用了FLEXCAN_UserRxCallback函数,在该函数中可以进行一些额外的处理,例如打印日志或修改数据。 需要注意的是,由于CAN和UART是两种不同的通信协议,因此在转换数据时需要进行一些协议转换,例如将CAN数据帧的格式转换为UART数据的格式。此外,由于CAN和UART的数据传输速率有所不同,因此在转换数据时需要考虑数据传输的速率和延迟,以确保数据的正确性和实时性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值