UART_SEND详细设计方案

本文介绍了一种基于50MHz时钟的UART串口发送模块设计,详细阐述了如何通过计数器实现9600波特率的串口数据发送,并提供了完整的VerilogHDL源代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.      UART_SEND简介:

串口是用的非常多的一种接口,实现原理比较简单,基本所有CPU芯片都配置有串口,所以经常被用来作为调试接口。

2.      UART_SEND规格:

实现9600波特率的串口发送,上位机串口软件可以接收到发送的数据。

 

3.      实现原理

以波特率9600为例子说明,波特率9600接收一个bit的时间为1s/9600=104us,即每隔104us发送一个数据。

 

104us = 104000ns 50M时钟的一个周期时间为20ns要远小于104000ns,所以可以用50M时钟产生的计数器来计数,然后根据计数器来发送数据。

 

新建一个计数器,50Mhz为时钟,那么计数器变化一次时间为20ns。

由于一次完整数据接收需要有1144000ns时间,所以计数器必须记到1144000ns时间。

1144000ns/20ns = 57200,所以需要16位计数器。

 

Startbit(0)占据计数器的0   -104000ns/20ns = 5200

D0           占据计数器的5200-208000ns/20ns = 10400

D1           占据计数器的10400-312000ns/20ns = 15600

D2           占据计数器的15600-416000ns/20ns = 20800

D3           占据计数器的20800-520000ns/20ns = 26000

D4           占据计数器的26000-624000ns/20ns = 31200

D5           占据计数器的31200-728000ns/20ns = 36400

D6           占据计数器的36400-832000ns/20ns = 41600

D7           占据计数器的41600-936000ns/20ns = 46800 

校验位       占据计数器的46800-1040000ns/20ns = 52000

Endbit(1)  占据计数器的52000-1144000ns/20ns = 57200

4.      Verilog HDL源代码

Verilog HDL代码为:

 

moduleUartSend (

              //input

              sys_clk        ,

              sys_rst_n      ,

              data_in        ,             //data in 8bit

 

              //output

              uart_txd

              );

 

//inputports

 

input                    sys_clk             ;    //system clock;

input                    sys_rst_n           ;   //system reset, low is active;

input[WIDTH-1:0]        data_in             ;    //to send data  8bit ;   

 

//outputports

output                   uart_txd            ;   //uart txd output ;  

 

//regdefine

reg    [WIDTH-1:0]       buff                ;        

reg    [WIDTH-1:0]       data_out            ;

 

reg                      uart_txd            ;   

reg                      txd                 ;    //temp txd signal;

    

reg  [SIZE-1:0]          counter             ;    

    

//wiredefine

 

//parameterdefine

parameterWIDTH = 8;

parameterSIZE  = 16;

 

/*******************************************************************************************************

**                              Main Program   

** 

********************************************************************************************************/

always@(posedge sys_clk or negedge sys_rst_n) begin

        if (sys_rst_n ==1'b0) begin

            buff <= 8'b0;

        end

        else

            buff  <= data_in ;

end

       

always@(posedge sys_clk or negedge sys_rst_n) begin

        if (sys_rst_n ==1'b0) begin

            counter <= 16'b0;

        end

        else if (counter > 57200 )    

            counter <= 16'b0;

        else

            counter  <= counter + 1'b1;

end

 

always@(*) begin

    if ((counter > 0)         &&  (counter <= 5200 ))  

       txd =  1'b0  ;                       

    else if ((counter > 5200)&&  (counter  <= 10400))  

       txd =  buff[0]  ;                    

    else if ((counter > 10400) &&(counter  <= 15600))  

       txd =  buff[1]  ;                    

    else if ((counter > 15600) &&(counter  <= 20800))  

       txd =  buff[2]  ;                     

    else if ((counter > 20800) &&(counter  <= 26000))  

       txd =  buff[3]  ;                    

    else if ((counter > 26000) &&(counter  <= 31200))  

       txd =  buff[4]  ;                    

    else if ((counter > 31200) &&(counter  <= 36400))  

       txd =  buff[5]  ;                    

    else if ((counter > 36400) &&(counter  <= 41600))  

       txd =  buff[6]  ;                    

    else if ((counter > 41600) &&(counter  <= 46800))  

       txd =  buff[7]  ;                    

    else if ((counter > 46800) &&(counter  <= 52000))  

       txd =  1'b1     ;                    

    else if ((counter > 52000) &&(counter  <= 57200))

       txd =  1'b1     ;       

    else           

       txd =  1'b1  ; 

end       

 

 

always@(posedge sys_clk or negedge sys_rst_n) begin

        if (sys_rst_n ==1'b0) begin

           uart_txd <= 1'b1;       

        end

        else 

           uart_txd  <= txd;       

          

end

 

endmodule

//endof RTL code     

static struct hc32_uart_cfg_types uart_cfg_type[UART_MAX_CHANNEL] = { { RS485_CHANNEL_2, //uart通道配置 CM_USART1, //Uart寄存器 &Uart1TxBuffer, //uart收发缓冲区 //DIO_CHANNEL_RS485_2_CRTL,//Dio_ChannelType ctrl_io; //uart流控管脚 //STD_HIGH,//Dio_LevelType send_level; //流控管脚的电平状态 &uart_clck_cfg[RS485_CHANNEL_2], //clk_cfg }, { RS485_CHANNEL_0, CM_USART3, &Uart3TxBuffer, //DIO_CHANNEL_RS485_0_CRTL,//Dio_ChannelType ctrl_io; //STD_HIGH,//Dio_LevelType send_level; &uart_clck_cfg[RS485_CHANNEL_0], //clk_cfg }, { UART_CHANNEL_4, CM_USART4, &Uart4TxBuffer, //DIO_CHANNEL_NONEL,//Dio_ChannelType ctrl_io; //STD_HIGH,//Dio_LevelType send_level; &uart_clck_cfg[UART_CHANNEL_4], //clk_cfg }, { RS485_CHANNEL_1, CM_USART6, &Uart6TxBuffer, //DIO_CHANNEL_RS485_1_CRTL,//Dio_ChannelType ctrl_io; //STD_HIGH,//Dio_LevelType send_level; &uart_clck_cfg[RS485_CHANNEL_1], //clk_cfg }, }; const struct hc32_uart_platform UART_platforms[UART_MAX_CHANNEL] = { {//uart_1 &uart_cfg_type[RS485_CHANNEL_2] //struct hc32_uart_cfg_typess USART_STOPBIT_1BIT, USART_DATA_WIDTH_8BIT, 9600U, }, {//uart_3 &uart_cfg_type[RS485_CHANNEL_0] //struct hc32_uart_cfg_typess USART_STOPBIT_1BIT, USART_DATA_WIDTH_8BIT, 9600U, }, {//uart_4 &uart_cfg_type[UART_CHANNEL_4] //struct hc32_uart_cfg_typess USART_STOPBIT_1BIT, USART_DATA_WIDTH_8BIT, 9600U, }, {//uart_6 &uart_cfg_type[RS485_CHANNEL_1] //struct hc32_uart_cfg_typess USART_STOPBIT_1BIT, USART_DATA_WIDTH_8BIT, 9600U, }, }; &uart_cfg_type[RS485_CHANNEL_2] //struct hc32_uart_cfg_typess ^ "D:\code\P76\arch\HC32F467\Uart_Lcfg.c",87 Error[Pe059]: function call is not allowed in a constant expression &uart_cfg_type[RS485_CHANNEL_0] //struct hc32_uart_cfg_typess ^ "D:\code\P76\arch\HC32F467\Uart_Lcfg.c",93 Error[Pe059]: function call is not allowed in a constant expression &uart_cfg_type[UART_CHANNEL_4] //struct hc32_uart_cfg_typess ^ "D:\code\P76\arch\HC32F467\Uart_Lcfg.c",99 Error[Pe059]: function call is not allowed in a constant expression &uart_cfg_type[RS485_CHANNEL_1] //struct hc32_uart_cfg_typess ^ "D:\code\P76\arch\HC32F467\Uart_Lcfg.c",105 Error[Pe059]: function call is not allowed in a constant expression
最新发布
07-26
../Core/Src/main.c:75:12: error: expected '=', ',', ';', 'asm' or '__attribute__' before '.' token 75 | Uart1_State.huart = &huart1; | ^ ../Core/Src/main.c:76:12: error: expected '=', ',', ';', 'asm' or '__attribute__' before '.' token 76 | Uart2_State.huart = &huart2; | ^ ../Core/Src/main.c: In function 'main': ../Core/Src/main.c:150:5: warning: implicit declaration of function 'uart_send_string'; did you mean 'usart2_send_lora_string'? [-Wimplicit-function-declaration] 150 | uart_send_string(&Uart1_State, uTxBuffer, TXBUFFERSIZE); | ^~~~~~~~~~~~~~~~ | usart2_send_lora_string ../Core/Src/main.c: At top level: ../Core/Src/main.c:350:6: warning: conflicting types for 'uart_send_string'; have 'void(UART_State *, uint8_t *, uint16_t)' {aka 'void(UART_State *, unsigned char *, short unsigned int)'} 350 | void uart_send_string(UART_State *state, uint8_t *buffer, uint16_t size) { | ^~~~~~~~~~~~~~~~ ../Core/Src/main.c:150:5: note: previous implicit declaration of 'uart_send_string' with type 'void(UART_State *, uint8_t *, uint16_t)' {aka 'void(UART_State *, unsigned char *, short unsigned int)'} 150 | uart_send_string(&Uart1_State, uTxBuffer, TXBUFFERSIZE); | ^~~~~~~~~~~~~~~~ ../Core/Src/main.c: In function 'uart_send_string': ../Core/Src/main.c:364:29: error: 'USART_TypeDef' has no member named 'DR'; did you mean 'RDR'? 364 | state->huart->Instance->DR = buffer[0]; | ^~ | RDR make: *** [Core/Src/subdir.mk:49: Core/Src/main.o] Error 1 make: *** Waiting for unfinished jobs.... ../Core/Src/stm32f0xx_it.c: In function 'USART1_IRQHandler': ../Core/Src/stm32f0xx_it.c:234:13: error: 'Uart1_State' undeclared (first use in this function) 234 | if (Uart1_State.Tx_Count < Uart1_State.Tx_Size) { | ^~~~~~~~~~~ ../Core/Src/stm32f0xx_it.c:234:13: note: each undeclared identifier is reported only once for each function it appears in ../Core/Src/stm32f0xx_it.c:235:30: error: 'USART_TypeDef' has no member named 'DR'; did you mean 'RDR'? 235 | huart1.Instance->DR = Uart1_State.Tx_Buffer[Uart1_State.Tx_Count++]; | ^~ | RDR ../Core/Src/stm32f0xx_it.c: In function 'USART2_IRQHandler': ../Core/Src/stm32f0xx_it.c:262:11: error: 'Uart2_State' undeclared (first use in this function) 262 | if (Uart2_State.Tx_Count < Uart2_State.Tx_Size) { | ^~~~~~~~~~~ ../Core/Src/stm32f0xx_it.c:263:28: error: 'USART_TypeDef' has no member named 'DR'; did you mean 'RDR'? 263 | huart2.Instance->DR = Uart2_State.Tx_Buffer[Uart2_State.Tx_Count++]; | ^~ | RDR make: *** [Core/Src/subdir.mk:49: Core/Src/stm32f0xx_it.o] Error 1 "make -j12 all" terminated with exit code 2. Build might be incomplete.
07-22
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

浩瀚之水_csdn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值