• gd32f303在IAR下的printf串口助手打印+串口收发配置


    第一次用兆易创新32位arm,感觉同为国产,确实不如华大改动(创新)大,至少给人的感觉几乎照搬ST的,虽然两者开发可参考资料都少的可怜;
    对于USARTx的驱动配置步骤:
    https://blog.csdn.net/JackieCoo/article/details/126777665(可参考)
    1、以USART0为例(查询方式)
    使能GPIOA时钟;
    使能USART0时钟;
    使能复用功能AF时钟;
    配置GPIOA的输出模式AF-PP,50MZ,PA9 TX;
    配置GPIOA的输入模式IN-FLOATING,50MZ,PA10 RX;
    复位USART0;
    设置波特率115200;(主从机波特率一致)
    数据格式8bit数据位、无奇偶校验、1bit停止+1bit起始;
    使能发送器;
    使能接收器;
    使能USART0外设;
    (采用中断方式可使能中断收发标志,参考GD32官方库,以上都可直接调用GD32官方库函数实现,不用手动底层驱动配置);
    2、收发函数

    void  usart_reveive(uint8_t *r_array,uint8_t length)
    {
    	uint8_t j = 0;
    	while(j<length)
    	{	
    		while(RESET == usart_flag_get(USART0,USART_FLAG_RBNE));//这个接收标志是非空置1,就是当缓冲区不为空时,即有数据时要让CPU取走数据,即赋值给内存;当RBNE置1的时候跳出等待循环;
    		r_array[j] = usart_data_receive(USART0);
    		j++;
    	}
    }
    
    void  usart_send(uint8_t *t_array,uint8_t length)
    {
    	uint8_t i = 0;
    	while(i<length)
    	{	
    		usart_data_receive(USART0,USART_FLAG_TBE);
    		while(RESET == usart_flag_get(USART0,USART_FLAG_TBE));//这个发送标志是空置1,就是当缓冲区为空时,即缓冲区无数据时要让CPU去放数据,当TBE置1的时候跳出等待循环;
    		i++;
    	}
    }
    uint8_t receive_trans[10];//串口助手发10个,再原值返回给它10个
    int main()
    {
    	while(1)
    	{
    		//串口助手pc端与MCU的互动;
    		usart_reveive(receive_trans,10);
    		usart_send(receive_trans,10);
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    3、当写完编译烧录成功以后,你会发现串口助手未必就能正常显示你收发的数据,可能乱码(前提是你串口号,波特率,数据格式这些常规选择正确,这个就不用说了),这时候关键就需要你去看看你板子硬件电路提供的晶振源了,看看systemClock的时钟源到底是多少,官库里有get_XX_Clock函数(每种ARM片子都有相应的函数);一般都是默认的晶振源是内部RC振荡器,有的会接外部晶振(具体看你硬件板子怎么设计的);这个时候如果选用外部晶振源,官库里关于外部晶振的宏定义一定要保持和实际外部晶振源(比如说外接了一个16M的)一致;
    4、同样在IAR环境下使用printf要比keil好设置些,只需要调stdio.h函数,设置一下full,然后重定义fputc函数就行,如果出现乱码还是可能因为软件配置的时钟源的原因影响导致的;
    5、关于中断方式的收发逻辑:
    【注意】在连续接收的时候出现数据接收错位的原因?
    TXE置1的条件:是将数据(10bit)完全从buffer缓冲区拿出到移位寄存器后;
    RXNE置1的条件:是将数据(10bit)完全从移位寄存器移到buffer缓冲区后;
    例如:发送trans[6]=0,1,2,3,4,5(发送帧);接收receive[6] = 0,1,2,3,4,5(接收帧);中间协议假设已给定会按照发送帧和接收帧的内容顺序通信;但是实际过程中有 while(rxcount < rx_size) 这句接收等待和没有这句语句的区别就是,当有等待的时候会在一次轮询当中(一拍当中)完全等到数组receive[6]把6个数据接收赋值完成,所以顺序不会错位;但是当没有等待的时候,RXNE是每隔一个很短时间才置1的,data寄存器被读出后,标志清0退出ISR,然后主函数会在这个间隔去执行自己,有可能接收端的下个数据在路上时(亦还没到移位寄存器将数据完全移入biffer缓冲区时),主函数已经执行下一拍到重新开始发送处了,这时候又开始进行发送中断了,所以上一拍就相当于成功接收了一个字节的数据,如果连续3拍因为硬件的问题都只来的及成功接收一个字节,那就会出现receive[6] = 0,0,0,0,1,2(接收帧)的现象(还需要注意计数值是全局变量);所以当没有 while(rxcount < rx_size) 这句接收等待时,就只能靠硬件传输的足够快和连续,能将receive[6]这个6个字节数据在usart_interrupt_enable(USART0, USART_INT_RBNE)和txcount = rxcount = 0;之间执行进6次接收中断执行完,这样赋值顺序才不会错位,按照接收receive[6] = 0,1,2,3,4,5(接收帧);

    uint8_t tx_size = TRANSMIT_SIZE;
    uint8_t rx_size = 32;
    uint8_t txcount = 0; 
    uint16_t rxcount = 0;   //注意计数值是全局变量
    /* enable USART TBE interrupt */  
        usart_interrupt_enable(USART0, USART_INT_TBE);
        
        /* wait until USART send the transmitter_buffer */
        while(txcount < tx_size);
        
        while(RESET == usart_flag_get(USART0, USART_FLAG_TC));
        
        usart_interrupt_enable(USART0, USART_INT_RBNE);  //
        
        /* wait until USART receive the receiver_buffer */
        while(rxcount < rx_size);
        txcount = rxcount = 0;
    
    /***********************************************************************/
    void USART0_IRQHandler(void)
    {
        if(RESET != usart_interrupt_flag_get(USART0, USART_INT_FLAG_RBNE)){
            /* receive data */
            rxbuffer[rxcount++] = usart_data_receive(USART0);
            if(rxcount == rx_size){
                usart_interrupt_disable(USART0, USART_INT_RBNE);
            }
        }
        if(RESET != usart_interrupt_flag_get(USART0, USART_INT_FLAG_TBE)){
            /* transmit data */
            usart_data_transmit(USART0, txbuffer[txcount++]);
            if(txcount == tx_size){
                usart_interrupt_disable(USART0, USART_INT_TBE);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
  • 相关阅读:
    【分享】GIS领域论坛社区
    吴恩达深度学习笔记(六)——超参数调试、Batch正则化和程序框架
    TouchGFX之二进制字体
    嵌入式系统中的FPGA
    软件测试外包是什么意思
    TYVJ P1026 犁田机器人
    python 脏话处理、特殊词汇过滤!
    文件系统(八):Linux JFFS2文件系统工作原理、优势与局限
    详细解读 React useCallback &useMemo
    计算机毕业设计Java网上鲜花交易平台(源码+系统+mysql数据库+Lw文档)
  • 原文地址:https://blog.csdn.net/SUR0608/article/details/127457322