精华内容
下载资源
问答
  • STM32串口发送数据和接收数据方式总结

    万次阅读 多人点赞 2018-05-13 20:34:22
    之前写了篇关于ESP8266使用AT指令进行互相通讯的实验,在写STM...串口发送数据: 1. 串口发送数据最直接的方式就是标准调用库函数。void USART_SendData(USART_TypeDef* USARTx, uint16_t Data); 第一个参数是发送...

     

           之前写了篇关于ESP8266使用AT指令进行互相通讯的实验,在写STM32串口接发数据的程序中,觉得有必要将之前学的有关于串口方面的使用经历加以总结。

     

    串口发送数据:

           1. 串口发送数据最直接的方式就是标准调用库函数  void USART_SendData(USART_TypeDef* USARTx, uint16_t Data);
    第一个参数是发送的串口号,第二个参数是要发送的数据了。但是用过的朋友应该觉得不好用,一次只能发送单个字符,所以我们有必要根据这个函数加以扩展。

    void Send_data(u8 *s)
    {
    	while(*s!='\0')
    	{ 
    		while(USART_GetFlagStatus(USART1,USART_FLAG_TC )==RESET);	
    		USART_SendData(USART1,*s);
    		s++;
    	}
    }

            以上程序的形参就是我们调用该函数时要发送的字符串,这里通过循环调用USART_SendData来一 一发送我们的字符串。

    while(USART_GetFlagStatus(USART1,USART_FLAG_TC )==RESET);

             这句话有必要加,他是用于检查串口是否发送完成的标志,如果不加这句话会发生数据丢失的情况。这个函数只能用于串口1发送。有些时候根据需要,要用到多个串口发送那么就还需要改进这个程序。如下: 

    void Send_data(USART_TypeDef * USARTx,u8 *s)
    {
    	while(*s!='\0')
    	{ 
    		while(USART_GetFlagStatus(USARTx,USART_FLAG_TC )==RESET);	
    		USART_SendData(USARTx,*s);
    		s++;
    	}
    }

            这样就可实现任意的串口发送。但有一点,我在使用实时操作系统的时候(如UCOS,Freertos等),需考虑函数重入的问题。当然也可以简单的实现把该函数复制一下,然后修改串口号也可以避免该问题。然而这个函数不能像printf那样传递多个参数,所以还可以在改进,最终程序如下

    void USART_printf ( USART_TypeDef * USARTx, char * Data, ... )
    {
    	const char *s;
    	int d;   
    	char buf[16];
    	
    	va_list ap;
    	va_start(ap, Data);
    
    	while ( * Data != 0 )     // 判断是否到达字符串结束符
    	{				                          
    		if ( * Data == 0x5c )  //'\'
    		{									  
    			switch ( *++Data )
    			{
    				case 'r':							          //回车符
    				USART_SendData(USARTx, 0x0d);
    				Data ++;
    				break;
    
    				case 'n':							          //换行符
    				USART_SendData(USARTx, 0x0a);	
    				Data ++;
    				break;
    
    				default:
    				Data ++;
    				break;
    			}			 
    		}
    		
    		else if ( * Data == '%')
    		{									  //
    			switch ( *++Data )
    			{				
    				case 's':										  //字符串
    				s = va_arg(ap, const char *);
    				
    				for ( ; *s; s++) 
    				{
    					USART_SendData(USARTx,*s);
    					while( USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET );
    				}
    				
    				Data++;
    				
    				break;
    
    				case 'd':			
    					//十进制
    				d = va_arg(ap, int);
    				
    				itoa(d, buf, 10);
    				
    				for (s = buf; *s; s++) 
    				{
    					USART_SendData(USARTx,*s);
    					while( USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET );
    				}
    				
    				Data++;
    				
    				break;
    				
    				default:
    				Data++;
    				
    				break;
    				
    			}		 
    		}
    		
    		else USART_SendData(USARTx, *Data++);
    		
    		while ( USART_GetFlagStatus ( USARTx, USART_FLAG_TXE ) == RESET );
    		
    	}
    }

            该函数就可以像printf使用可变参数,方便很多。通过观察函数但这个函数只支持了%d,%s的参数,想要支持更多,可以仿照printf的函数写法加以补充。
            2. 直接使用printf函数。        很多朋友都知道想要STM32要直接使用printf不行的。需要加上以下的重映射函数

           如果不想添加以上代码,也可以勾选以下的Use MicroLI选项来支持printf函数使用。

     

    串口接收数据:       

            串口接收最后应有一定的协议,如发送一帧数据应该有头标志或尾标志,也可两个标志都有。这样在处理数据时既能能保证数据的正确接收,也有利于接收完后我们处理数据。串口的配置在这里就不在赘述,这里我以串口2接收中断服务程序函数且接收的数据包含头尾标识为例。

    #define Max_BUFF_Len 18
    unsigned char Uart2_Buffer[Max_BUFF_Len];
    unsigned int Uart2_Rx=0;
    void USART2_IRQHandler() 
    {
    	if(USART_GetITStatus(USART2,USART_IT_RXNE) != RESET) //中断产生 
    	{
    		USART_ClearITPendingBit(USART2,USART_IT_RXNE); //清除中断标志
    			 
    		Uart2_Buffer[Uart2_Rx] = USART_ReceiveData(USART2);     //接收串口1数据到buff缓冲区
    		Uart2_Rx++; 
         		 
    		if(Uart2_Buffer[Uart2_Rx-1] == 0x0a || Uart2_Rx == Max_BUFF_Len)    //如果接收到尾标识是换行符(或者等于最大接受数就清空重新接收)
    		{
    			if(Uart2_Buffer[0] == '+')                      //检测到头标识是我们需要的 
    			{
    				printf("%s\r\n",Uart2_Buffer);        //这里我做打印数据处理
    				Uart2_Rx=0;                                   
    			} 
    			else
    			{
    				Uart2_Rx=0;                                   //不是我们需要的数据或者达到最大接收数则开始重新接收
    			}
    		}
    	}
    }

     


            数据的头标识为“\n”既换行符,尾标识为“+”。该函数将串口接收的数据存放在USART_Buffer数组中,然后先判断当前字符是不是尾标识,如果是说明接收完毕,然后再来判断头标识是不是“+”号,如果还是那么就是我们想要的数据,接下来就可以进行相应数据的处理了。但如果不是那么就让Usart2_Rx=0重新接收数据。这样做的有以下好处:

            1.可以接受不定长度的数据,最大接收长度可以通过Max_BUFF_Len来更改

            2.可以接受指定的数据

            3.防止接收的数据使数组越界
            这里我的把接受正确数据直接打印出来,也可以通过设置标识位,然后在主函数里面轮询再操作。

            

            以上的接收形式,是中断一次就接收一个字符,这在UCOS等实时内核系统中频繁的中断,非常消耗CPU资源,在有些时候我们需要接收大量数据时且波特率很高的情况下,长时间中断会带来一些额外的问题。所以以DMA形式配合串口的IDLE(空闲中断)来接受数据将会大大的提高CPU的利用率,减少系统资源的消耗。首先还是先看代码。

    #define DMA_USART1_RECEIVE_LEN 18
    void USART1_IRQHandler(void)                                 
    {     
        u32 temp = 0;  
        uint16_t i = 0;  
          
        if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)  
        {  
            USART1->SR;  
            USART1->DR; //这里我们通过先读SR(状态寄存器)和DR(数据寄存器)来清USART_IT_IDLE标志 			
            DMA_Cmd(DMA1_Channel5,DISABLE);  
            temp = DMA_USART1_RECEIVE_LEN - DMA_GetCurrDataCounter(DMA1_Channel5); //接收的字符串长度=设置的接收长度-剩余DMA缓存大小 
            for (i = 0;i < temp;i++)  
            {  
                Uart2_Buffer[i] = USART1_RECEIVE_DMABuffer[i];  
                    
            }  
            //设置传输数据长度  
            DMA_SetCurrDataCounter(DMA1_Channel5,DMA_USART1_RECEIVE_LEN);  
            //打开DMA  
            DMA_Cmd(DMA1_Channel5,ENABLE);  
        }        
    } 

            之前的串口中断是一个一个字符的接收,现在改为串口空闲中断,就是一帧数据过来才中断进入一次。而且接收的数据时候是DMA来搬运到我们指定的缓冲区(也就是程序中的USART1_RECEIVE_DMABuffer数组),是不占用CPU时间资源的。具体什么是IDLE中断和DMA需要朋友们先行了解。

        参考链接:

        https://blog.csdn.net/jdh99/article/details/8444474

        https://blog.csdn.net/phker/article/details/51925668   

       最后在讲下DMA的发送

    #define DMA_USART1_SEND_LEN 64
    void DMA_SEND_EN(void)
    {
    	DMA_Cmd(DMA1_Channel4, DISABLE);      
    	DMA_SetCurrDataCounter(DMA1_Channel4,DMA_USART1_SEND_LEN);   
    	DMA_Cmd(DMA1_Channel4, ENABLE);
    }

            这里需要注意下DMA_Cmd(DMA1_Channel4,DISABLE)函数需要在设置传输大小之前调用一下,否则不会重新启动DMA发送。

        有了以上的接收方式,对一般的串口数据处理是没有问题的了。下面再讲一下,在ucosiii中我使用信号量+消息队列+储存管理的形式来处理我们的串口数据。先来说一下这种方式对比其他方式的一些优缺点。一般对串口的处理形式是"生产者"和"消费者"的模式,即本次接收的数据要马上处理,否则当数据大量涌进的时候,就来不及"消费"掉生产者(串口接收中断)的数据,那么就会丢失本次的数据处理。所以使用队列就能够很方便的解决这个问题。

        在下面的程序中,对数据的处理是先接受,在处理,如果在处理的过程中,有串口中断接受数据,那么就把它依次放在队列中,队列的特征是先进先出,在串口中就是先处理先接受的数据,所以根据生产和消费的速度,定义不同大小的消息队列缓冲区就可以了。缺点就是太占用系统资源,一般51单片机是没可能了。下面是从我做的项目中截取过来的程序

    OS_MSG_SIZE  Usart1_Rx_cnt;          //字节大小计数值
    unsigned char Usart1_data;           //每次中断接收的数据
    unsigned char* Usart1_Rx_Ptr;        //储存管理分配内存的首地址的指针
    unsigned char* Usart1_Rx_Ptr1;       //储存首地址的指针
    void USART1_IRQHandler() 
    {
    	OS_ERR err;
    	OSIntEnter();
    	
      if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE) != RESET) //中断产生 
      { 	 
        USART_ClearFlag(USART1, USART_FLAG_RXNE);     //清除中断标志
    		
        Usart1_data = USART_ReceiveData(USART1);     //接收串口1数据到buff缓冲区
    		
    		if(Usart1_data =='+')                     //接收到数据头标识
    		{
    //			OSSemPend((OS_SEM*		)&SEM_IAR_UART,  //这里请求信号量是为了保证分配的存储区,但一般来说不允许
    //			(OS_TICK		)0,                   //在终端服务函数中调用信号量请求但因为
    //			(OS_OPT			)OS_OPT_PEND_NON_BLOCKING,//我OPT参数设置为非阻塞,所以可以这么写
    //			(CPU_TS*		)0,
    //			(OS_ERR*		)&err); 
    //			if(err==OS_ERR_PEND_WOULD_BLOCK)	    //检测到当前信号量不可用
    //			{
    //				 printf("error");
    //			}				
    			Usart1_Rx_Ptr=(unsigned char*) OSMemGet((OS_MEM*)&UART1_MemPool,&err);//分配存储区
    			Usart1_Rx_Ptr1=Usart1_Rx_Ptr;		        //储存存储区的首地址
    		}
    		if(Usart1_data == 0x0a )   				//接收到尾标志
    		{                    
    			*Usart1_Rx_Ptr++=Usart1_data;
    			Usart1_Rx_cnt++;                        	//字节大小增加
    			OSTaskQPost((OS_TCB    *  )&Task1_TaskTCB,
                                       (void      *  )Usart1_Rx_Ptr1,    //发送存储区首地址到消息队列
                                       (OS_MSG_SIZE  )Usart1_Rx_cnt,
                                       (OS_OPT       )OS_OPT_POST_FIFO,  //先进先出,也可设置为后进先出,再有地方很有用
                                       (OS_ERR    *  )&err);
    									
    			Usart1_Rx_Ptr=NULL;          //将指针指向为空,防止修改
    			Usart1_Rx_cnt=0;	     //字节大小计数清零
    		}
    		else
    		{
    			*Usart1_Rx_Ptr=Usart1_data; //储存接收到的数据
    			Usart1_Rx_Ptr++;
    			Usart1_Rx_cnt++;
    		}	
    	}		 	
    	OSIntExit();
    }

           上面被注释掉的代码为我是为了防止当分区中没有空闲的存储块时加入信号量,打印出报警信息。当然我们也可以将存储块直接设置大一点,但是还是无法避免当没有可有存储块时会程序会崩溃现象。希望懂的朋友能告知下~。

            下面是串口数据处理任务,这里删去了其他代码,只把他打印出来了而已。

    void task1_task(void *p_arg)
    {
    	OS_ERR err;
    	OS_MSG_SIZE Usart1_Data_size;
    	u8 *p;
    	
    	while(1)
    	{
    		p=(u8*)OSTaskQPend((OS_TICK		)0, //请求消息队列,获得储存区首地址
    			(OS_OPT				)OS_OPT_PEND_BLOCKING,
    			(OS_MSG_SIZE*	)&Usart1_Data_size,
    			(CPU_TS*			)0,
    			(OS_ERR*			)&err);
    
    		printf("%s\r\n",p);        //打印数据
    
    		delay_ms(100);
    		OSMemPut((OS_MEM*	)&UART1_MemPool,    //释放储存区
    		(void*			)p,
    		(OS_ERR*		)&err);
    						 
    		OSSemPost((OS_SEM*	)&SEM_IAR_UART,    //释放信号量
    		(OS_OPT 	)OS_OPT_POST_NO_SCHED,
    		(OS_ERR*	)&err);
    						 
    		OSTimeDlyHMSM(0,0,1,500,OS_OPT_TIME_PERIODIC,&err);				 
    	}
    }

     

     

     

    展开全文
  • FPGA串口发送16位数

    千次阅读 2019-05-08 20:49:17
    近期调试FPGA,用到串口模块,之前没写过串口发送16位数的实验,最近调试通了,上来分享一下。 主要思想其实和正常的串口发送模块差不多,就是多定义几个状态变量,设置好时序就行。本模块实现的功能是:时钟来之后...
    近期调试FPGA,用到串口模块,之前没写过串口发送16位数的实验,最近调试通了,上来分享一下。
    主要思想其实和正常的串口发送模块差不多,就是多定义几个状态变量,设置好时序就行。本模块实现的功能是:时钟来之后开始计数,计到一定值之后启动串口发送模块,将数发送出去。就是很简单的串口发送模块,主要提供给初学者参考。
    
    module UART_Tx(
    	input       clk,
    	input       rst_n,
    	
    	output reg  txd
    );
    
    parameter S_IDLE = 5'd0;             //空闲状态
    parameter S_START_L = 5'd1;          //发送低八位起始位
    parameter S_BIT0_L = 5'd2;           //发送低八位数据位
    parameter S_BIT1_L = 5'd3;
    parameter S_BIT2_L = 5'd4;
    parameter S_BIT3_L = 5'd5;
    parameter S_BIT4_L = 5'd6;
    parameter S_BIT5_L = 5'd7;
    parameter S_BIT6_L = 5'd8;
    parameter S_BIT7_L = 5'd9;
    parameter S_STOP_L = 5'd10;          //发送低八位停止位
    
    parameter S_WAIT = 5'd11;            //等待一个串口时钟周期
    
    parameter S_START_H = 5'd12;          //发送高八位起始位
    parameter S_BIT0_H = 5'd13;           //发送高八位数据位
    parameter S_BIT1_H = 5'd14;
    parameter S_BIT2_H = 5'd15;
    parameter S_BIT3_H = 5'd16;
    parameter S_BIT4_H = 5'd17;
    parameter S_BIT5_H = 5'd18;
    parameter S_BIT6_H = 5'd19;
    parameter S_BIT7_H = 5'd20;
    parameter S_STOP_H = 5'd21;          //发送高八位停止位
    
    parameter CLK_F = 125000000;   //system clock frequency
    parameter UART_BPS = 9600;    //串口波特率
    localparam BPS_CNT = CLK_F/UART_BPS;  //相应波特率分频计数器
    
    parameter cnt=60000;                    //计数器记到cnt值后串口输出该值
    
    reg [4:0] state;
    reg[15:0] bit_timer;           //用于控制波特率的计数器如果波特率是115200,每个数据位50000000/115200个时钟周期
    reg[15:0] tx_data;             //串口发送接口
    reg[7:0]  tx_data_h;           //串口发送的高八位数据
    reg[7:0]  tx_data_l;           //串口发送的低八位数据
    
    
    always@(posedge clk or negedge rst_n)begin
    	if(!rst_n)begin
    		state <= S_IDLE;
    		bit_timer <= 16'd0;
    		txd <= 1'b1;
    		tx_data <= 16'd0;
    	end
    	else begin
    		case(state)
    			S_IDLE:begin
    				txd <= 1'b1;
    				bit_timer <= 16'd0;
    				tx_data <= tx_data + 16'd1;
    				if(tx_data == cnt)begin
    					tx_data_h <= tx_data[15:8];
    					tx_data_l <= tx_data[7:0];
    					//tx_data <= 0;
    					state <= S_START_L;
    				end
    				else
    					state <= state;
    			end
    			
    			S_START_L:begin
    				txd <= 1'b0;
    				if(bit_timer==BPS_CNT)begin
    					state <= S_BIT0_L;
    					bit_timer <= 16'd0;
    				end
    				else begin
    					state <= state;
    					bit_timer <= bit_timer + 16'd1;
    				end
    			end
    			
    			S_BIT0_L:begin
    				//txd <= tx_data[0];
    				txd <= tx_data_l[0];
    				if(bit_timer==BPS_CNT)begin
    					state <= S_BIT1_L;
    					bit_timer <= 16'd0;
    				end
    				else begin
    					state <= state;
    					bit_timer <= bit_timer + 16'd1;
    				end
    			end
    			
    			S_BIT1_L:begin
    				//txd <= tx_data[1];
    				txd <= tx_data_l[1];
    				if(bit_timer==BPS_CNT)begin
    					state <= S_BIT2_L;
    					bit_timer <= 16'd0;
    				end
    				else begin
    					state <= state;
    					bit_timer <= bit_timer + 16'd1;
    				end
    			end
    			
    			S_BIT2_L:begin
    				//txd <= tx_data[2];
    				txd <= tx_data_l[2];
    				if(bit_timer==BPS_CNT)begin
    					state <= S_BIT3_L;
    					bit_timer <= 16'd0;
    				end
    				else begin
    					state <= state;
    					bit_timer <= bit_timer + 16'd1;
    				end
    			end
    			
    			S_BIT3_L:begin
    				//txd <= tx_data[3];
    				txd <= tx_data_l[3];
    				if(bit_timer==BPS_CNT)begin
    					state <= S_BIT4_L;
    					bit_timer <= 16'd0;
    				end
    				else begin
    					state <= state;
    					bit_timer <= bit_timer + 16'd1;
    				end
    			end
    			
    			S_BIT4_L:begin
    				//txd <= tx_data[4];
    				txd <= tx_data_l[4];
    				if(bit_timer==BPS_CNT)begin
    					state <= S_BIT5_L;
    					bit_timer <= 16'd0;
    				end
    				else begin
    					state <= state;
    					bit_timer <= bit_timer + 16'd1;
    				end
    			end
    			
    			S_BIT5_L:begin
    				//txd <= tx_data[5];
    				txd <= tx_data_l[5];
    				if(bit_timer==BPS_CNT)begin
    					state <= S_BIT6_L;
    					bit_timer <= 16'd0;
    				end
    				else begin
    					state <= state;
    					bit_timer <= bit_timer + 16'd1;
    				end
    			end
    			
    			S_BIT6_L:begin
    				//txd <= tx_data[6];
    				txd <= tx_data_l[6];
    				if(bit_timer==BPS_CNT)begin
    					state <= S_BIT7_L;
    					bit_timer <= 16'd0;
    				end
    				else begin
    					state <= state;
    					bit_timer <= bit_timer + 16'd1;
    				end
    			end
    			
    			S_BIT7_L:begin
    				//txd <= tx_data[7];
    				txd <= tx_data_l[7];
    				if(bit_timer==BPS_CNT)begin
    					state <= S_STOP_L;
    					bit_timer <= 16'd0;
    				end
    				else begin
    					state <= state;
    					bit_timer <= bit_timer + 16'd1;
    				end
    			end
    			
    			S_STOP_L:begin
    				txd <= 1'b1;
    				if(bit_timer==BPS_CNT)begin
    					state <= S_START_H;
    					bit_timer <= 16'd0;
    				end
    				else begin
    					state <= state;
    					bit_timer <= bit_timer + 16'd1;
    				end
    			end
    			
    //			S_WAIT:begin
    //				txd <= 1'b1;
    //				if(bit_timer==BPS_CNT)begin
    //					state <= S_START_H;
    //					bit_timer <= 16'd0;
    //				end
    //				else begin
    //					state <= state;
    //					bit_timer <= bit_timer + 16'd1;
    //				end
    //			end
    			
    			S_START_H:begin
    				txd <= 1'b0;
    				if(bit_timer==BPS_CNT)begin
    					state <= S_BIT0_H;
    					bit_timer <= 16'd0;
    				end
    				else begin
    					state <= state;
    					bit_timer <= bit_timer + 16'd1;
    				end
    			end
    			
    			S_BIT0_H:begin
    				//txd <= tx_data[8];
    				txd <= tx_data_h[0];
    				if(bit_timer==BPS_CNT)begin
    					state <= S_BIT1_H;
    					bit_timer <= 16'd0;
    				end
    				else begin
    					state <= state;
    					bit_timer <= bit_timer + 16'd1;
    				end
    			end
    			
    			S_BIT1_H:begin
    				//txd <= tx_data[9];
    				txd <= tx_data_h[1];
    				if(bit_timer==BPS_CNT)begin
    					state <= S_BIT2_H;
    					bit_timer <= 16'd0;
    				end
    				else begin
    					state <= state;
    					bit_timer <= bit_timer + 16'd1;
    				end
    			end
    			
    			S_BIT2_H:begin
    				//txd <= tx_data[10];
    				txd <= tx_data_h[2];
    				if(bit_timer==BPS_CNT)begin
    					state <= S_BIT3_H;
    					bit_timer <= 16'd0;
    				end
    				else begin
    					state <= state;
    					bit_timer <= bit_timer + 16'd1;
    				end
    			end
    			
    			S_BIT3_H:begin
    				//txd <= tx_data[11];
    				txd <= tx_data_h[3];
    				if(bit_timer==BPS_CNT)begin
    					state <= S_BIT4_H;
    					bit_timer <= 16'd0;
    				end
    				else begin
    					state <= state;
    					bit_timer <= bit_timer + 16'd1;
    				end
    			end
    			
    			S_BIT4_H:begin
    				//txd <= tx_data[12];
    				txd <= tx_data_h[4];
    				if(bit_timer==BPS_CNT)begin
    					state <= S_BIT5_H;
    					bit_timer <= 16'd0;
    				end
    				else begin
    					state <= state;
    					bit_timer <= bit_timer + 16'd1;
    				end
    			end
    			
    			S_BIT5_H:begin
    				//txd <= tx_data[13];
    				txd <= tx_data_h[5];
    				if(bit_timer==BPS_CNT)begin
    					state <= S_BIT6_H;
    					bit_timer <= 16'd0;
    				end
    				else begin
    					state <= state;
    					bit_timer <= bit_timer + 16'd1;
    				end
    			end
    			
    			S_BIT6_H:begin
    				//txd <= tx_data[14];
    				txd <= tx_data_h[6];
    				if(bit_timer==BPS_CNT)begin
    					state <= S_BIT7_H;
    					bit_timer <= 16'd0;
    				end
    				else begin
    					state <= state;
    					bit_timer <= bit_timer + 16'd1;
    				end
    			end
    			
    			S_BIT7_H:begin
    				//txd <= tx_data[15];
    				txd <= tx_data_h[7];
    				if(bit_timer==BPS_CNT)begin
    					state <= S_STOP_H;
    					bit_timer <= 16'd0;
    				end
    				else begin
    					state <= state;
    					bit_timer <= bit_timer + 16'd1;
    				end
    			end
    			
    			S_STOP_H:begin
    				txd <= 1'b1;
    				if(bit_timer==BPS_CNT)begin
    					state <= S_IDLE;
    					bit_timer <= 16'd0;
    				end
    				else begin
    					state <= state;
    					bit_timer <= bit_timer + 16'd1;
    				end
    			end
    			
    			default: state <= S_IDLE;
    		endcase
    		end
    	
    	end
    
    endmodule
    
    
    展开全文
  • Arduino 串口发送16进制数据

    千次阅读 2020-09-02 17:09:30
    unsigned char a[236]={ 0XFD,0XFD,0X30,0X03,0X79,0XE3,0X00,0X34,0X64,0X00, 0XC0,0X00,0X43,0X00,0X1B,0X00,0X15,0X00,0X1B,0X00, 0X00,0X00,0X15,0X00,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF, 0XFF,0XFF,0XFF,0XFF,...
    unsigned char a[236]={
    	0XFD,0XFD,0X30,0X03,0X79,0XE3,0X00,0X34,0X64,0X00,
    	0XC0,0X00,0X43,0X00,0X1B,0X00,0X15,0X00,0X1B,0X00,
    	0X00,0X00,0X15,0X00,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,
    	0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,
    	0X01,0X12,0X22,0X12,0X21,0X12,0X12,0X21,0X12,0X11,
    	0X22,0X12,0X21,0X22,0X22,0X22,0X22,0X22,0X22,0X22,
    	0X22,0X21,0X22,0X12,0X21,0X11,0X22,0X22,0X21,0X11,
    	0X12,0X22,0X22,0X22,0X22,0X21,0X22,0X22,0X22,0X22,
    	0X22,0X22,0X22,0X22,0X22,0X22,0X22,0X22,0X22,0X22,
    	0X22,0X22,0X21,0X11,0X12,0X22,0X13,0XF0,0X00,0X00,
    	0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
    	0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
    	0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
    	0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
    	0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
    	0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
    	0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
    	0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
    	0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
    	0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
    	0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
    	0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
    	0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
    	0X05,0X76,0X00,0XF9,0XDF,0XDF
    };
    void setup()
    {
    	Serial.begin(9600);
    	Serial.write(a,236);
    }
    void loop() {
    }
    

     

    展开全文
  • 串口发送16进制数据

    千次阅读 2013-06-22 21:59:26
    串口调试助手时发现此工具可以发送 16进制的数据串 分析后,粗略实现如下:    // eg: unsigned char src[] = "02042A2A50575203" // 16进制的串 // 每1个字节可以存放2个16进制 // eg:16进制的 0x01 在...

    用串口调试助手时发现此工具可以发送 16进制的数据串

    分析后,粗略实现如下: 

     

    // eg: unsigned char src[] = "02042A2A50575203"  
    // 16进制的串 
    // 每1个字节可以存放2个16进制位
    // eg:16进制的 0x01 在内存中为(little-endian)   0000,0001   =  (0x0 << 4 | 0x1)
    //             0x2a                           0010,1010   =  (0x2 << 4 | 0xa)
    // 
    
    #define HEX_STR_LEN         17
    
    int hextoi(unsigned char * asic)
    {
        if(*asic >= 48 && *asic <= 57)
        {
            *asic -= 48;
        }
        else if(*asic >= 65 && *asic <= 70)
        {
            *asic = *asic - 65 + 10;
        }
        else if(*asic >= 97 && *asic <= 102)
        {
            *asic = *asic - 97 + 10;
        }
        else
        {
            return -1;
        }
        return 0;
    }
    
    int hex2numeric(void * src, unsigned int len, unsigned char * serialCmd)
    {
        if(src == NULL || serialCmd == NULL)
        {
            return -1;
        }
        
        unsigned char *sCmd = serialCmd;
        unsigned char *pStart = (unsigned char *)src;
        
        int i = 0;
        int j = 0;
        
        while(j < len/2)
        {
            if(!hextoi(&pStart[i]) && !hextoi(&pStart[i+1]))
            {
                sCmd[j] = ((pStart[i] << 4) | pStart[i+1]);
            }
            else
            {
                return -1;
            }
            j += 1;
            i += 2;  
        }
        return 0;
    }
    
    /***********************************************************
    
    * test
    * send data like this
    ***********************************************************/
    int main(int argc, char *argv[])
    {
    	int fd = -1;
    	unsigned char src[HEX_STR_LEN] = "02042A2A50575203";
    	unsigned char serialCmd[HEX_STR_LEN/2];
    
    	memset(serialCmd, 0x00, sizeof(serialCmd));
    	if(hex2numeric(src, HEX_STR_LEN, serialCmd) < 0)
    	{
    		// ...
    		return;
    	}
    	
    
            // open serial port
    	if((fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY)) < 0)
    	{
    
    		// ...
    		return ;
    	}
    
            SetSerialBaud(fd, B9600);
            SetSerialParity(fd, CS8, STOPB1, NULL);
            SetSerialFlowControl(fd, NOCTRL, 0);
    
    	// ...
    
    	write(fd, serialCmd, sizeof(serialCmd));
    
    	// ...
    
    	return 0;
    }
    


     

    展开全文
  • FPGA 学习笔记(十二) 如何用串口发送32位数据

    千次阅读 热门讨论 2017-03-16 15:24:40
    在笔者之前所用的串口中,串口一次只能发送数据为8,这跟串口通信的协议方式有关系。而最近笔者的项目中需要用到一次发送32的数据。笔者最开始想到的是32数据发送4次。 为了不改动原来的串口通信协议驱动,...
  • 单片机串口通信中,接收多位数据到数组,发送位数据的代码 // 下面的代码用于:单片机的串口何上位机的串口进行通信,上位机发送数据是“abcd”就开灯,如果是“abde”就关灯。 /*****************************...
  • STM32串口16位数据

    千次阅读 2021-02-07 19:22:45
    串口是单片机中常常使用的通信接口,通常我们发送数据是8bit的数据,但是有些时候,需要发送16bit的数据,比如高精度ADC的采样数据,这时候需要高低八位分开传,不能简单的使用官方的原函数,否则会造成高八位的...
  • 串口发送接收浮点型数据

    万次阅读 2018-09-13 15:25:49
    转自:... ... 在做下机通信时往往会用到串口,包括下机将数据传输给上位机,或者是下机与下机之间进行数据传输,这时候就会遇到发送数据的问题,单片机通过串口发送数据时...
  • 串口助手使用16进制发送数据

    千次阅读 2019-10-10 20:53:31
    目录如何使用串口助手发送16进制数据 如何使用串口助手发送16进制数据 错误示范: 正确示范: 作者:伏熊(专业:射频芯片设计、雷达系统。爱好:嵌入式。欢迎大家项目合作交流。) 微信:GuoFengDianZi 引用: ...
  • 串口发送数据和接收数据,在此作一个简单的Demo.此Demo可以实现按下硬件按钮,灯亮,发送灯状态数据过来。并且可以实现几个灯同时亮,发送灯的状态数据过来。PC端实现点击按钮让硬件灯亮。 此处为4个灯,发送过来...
  • num = ['7d';'8a';'d7']; num = hex2dec(num ); fprintf(sr3,num );...原理就是把16进制转化为10进制,再以进制发送串口以十六进制接收的时候就是接受的原始数据,好简单,卡了一个小时。。。。渣渣的我 ...
  • 最近为了配置一个芯片使用到了串口发送9位数据位的情况,在此小记一下。 1. 串口硬件和参数初始化 将数据位宽度配置成:UART_WORDLENGTH_9B ,其他参数和常规大同小异。 UART_HandleTypeDef husart3; void HAL_UART...
  • 串口发送一帧数据时,两个字节的间隔时间是多少?
  • 串口发送32bit数据Verilog

    千次阅读 2017-10-12 16:48:18
    `define NUMBER 41//32bit字符数据的长度(要加上起始和停止) //`define NUMBER 11//8bit字符数据 //`define NUMBER 21//16bit字符数据 //`define NUMBER 31//24bit字符数据 `define NUMWIDTH 5//NUMBER的范围0...
  • QT串口发送十六进制数据接收串口数据并十六进制显示[喝小酒的网摘]http://blog.const.net.cn/a/4098.htm 代码如下:  struct PortSettings myComSetting = {BAUD9600,DATA_8,PAR_NONE,STOP_1,FLOW_OFF,10};  //...
  • MFC串口通信发送16进制数据

    万次阅读 2018-05-15 17:01:32
    发送数据一般是在edit control 里输入自己想发送的内容,然后点击send button。如果直接发送字符串内容,通过下面代码(send button内写入)即可: UpdateData(true); //读取编辑框内容 m_mscomm.put_Output...
  • labview串口发送与接收数据格式问题

    万次阅读 2016-10-02 19:28:33
    当我在网上搜索串口发送数据格式的问题是会得到这样的结果:labview中发送的是ascll,当你在labview中发送0的时候,在串口助手中会得到48,若想发送十六进制加上字符串到字节数组转换,对于我们新手来说,可能不太...
  • S 串口编程 详解4 串口发送数据

    千次阅读 2013-10-31 11:39:25
    S 串口编程 详解4 串口发送数据 串口发送数据包括: 十六进制发送数据 手动发送数据 自动发送数据 手动发送数据的代码如下: //手动发送 long TX_count=0; void CSCOMMDlg::OnButtonManualsend() { if...
  • STM32串口发送数据

    万次阅读 2019-05-15 15:35:53
    串口通信经常作为开发调试的工具,所以先介绍下串口通信。 串口通讯(Serial Communication)是一种设备间非常常用的串行通讯方式,因为它简单便捷,大部分电子设备都支持该通讯方式,电子工程师在调试设备时也经常...
  • STM串口发送数据无法发送第一个数据的解决方法
  • 51单片机 串口发送数据(只是发送)用于调试。 #include <reg51.h> #define uchar unsigned char #define uint unsigned int #define XTAL 11059200 // CUP 晶振频率 #define baudrate 9600 // 通信波特...
  • 之前写了篇关于ESP8266使用AT指令进行互相...串口发送数据: 1. 串口发送数据最直接的方式就是标准调用库函数。void USART_SendData(USART_TypeDef* USARTx, uint16_t Data); 第一个参数是发送的串口号,第二个参数...
  • 串口发送float型数据与解析

    千次阅读 2018-05-22 23:15:51
    最近在做智能车,采用了多CPU的方案,各个传感器分别采用了一个cpu进行数据的处理,然后将处理后的数据通过串口发送到另一块主控cpu 上。但在我以前应用串口时,都只是把字符类型或者字符串类型的数据发到串口。由于...
  • Python 串口发送十六进制数据

    千次阅读 2021-01-19 13:23:09
    0.安装 这里我们需要安装python的serial库,由于网络原因,我们使用豆瓣的pip源 ...# 配置串口基本参数并建立通信 ser = serial.Serial("COM1", 9600, 8, "E", timeout=50,stopbits=1) # 数据帧 a='68 AA AA AA AA AA.
  • VC++ 16进制串口发送和接收数据,可以选择串口速率和串口号,设置发送和接收的数据编码是否是十六进制,当接收区内容过多时可清空内容区。将一个字符串作为十六进制串转化为一个字节数组,字节间可用空格分隔,返回...
  • 串口发送数据速度

    千次阅读 2018-08-31 16:05:00
    这个取决于发送的波特率和设置的缓冲区大小按9600波特率来说, 1个起始 8个数据位 1个停止那么 9600/10=960Bytes 也就是每秒钟的数据量不会超过960字节如果波特率提高到115200 则可以达到11.52KB/S...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 83,726
精华内容 33,490
关键字:

串口发送16位数据