[单片机] MCU串口发送C方案优化

应用场景:

 

  主频不高非操作系统的单片机,需要在while循环中发送 数据到上位机,当数据较长时,会让发送的过程会让其他操作有卡顿感。为了解决这个问题,需采用一种方法:在每次大循环中只发一个字节数据,直到发送完毕。


#include <stdio.h>
#include <unistd.h>
void msleep(int ms)
{
	usleep(1000*ms);
}


//=============================================
#define MAX_SEND_LEN 10

u8 g_sendBuffer1[MAX_SEND_LEN]={ 0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa };
u8 g_sendBuffer2[MAX_SEND_LEN]={ 0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba };


//用printf打印输出,模拟单片机发送单字符
void UART_Send_Byte(u8 ch)
{
	printf("%02X ",ch);
}

int loop_send_uart(u8 *data,int delaycnt )
{
	static int send_index = -1;
	static int send_delayCnt =0;

	send_index++;
	
	if( send_index == 0 )
	{
		send_delayCnt = delaycnt;
	}	
    else if( send_index >= MAX_SEND_LEN)
	{
		if(--send_delayCnt<=0)
		{
			send_index = -1;
			send_delayCnt = delaycnt;
			return 0xFF;//finish signal
		}	
		else
			return send_index;
	}	
	UART_Send_Byte( data[send_index] );
	return send_index;
}
 
int main(int argc, char **argv)
{
    printf("=======C_BuildTime=[%s]==============\r\n\r\n",__TIME__ );
	
	int cnt = 0;
	int ret_index = 0;
	while(1)
	{
		printf("A_count = %d ::", cnt++ );
		printf("send_DATA=[");
		ret_index = loop_send_uart(g_sendBuffer1,3);
		printf("],ret_index=%02x.\n",ret_index );
		msleep(500);
		if(ret_index==0xFF) //发送完第1组数据
			break;
	}
	
	while(1)
	{
		printf("B_count = %d ::", cnt++ );
		printf("send_DATA=[");
		ret_index = loop_send_uart(g_sendBuffer2,3);
		printf("],ret_index=%02x.\n",ret_index );
		msleep(500);
		if(ret_index==0xFF) //发送完第2组数据
			break;
	}	
    return 0;
}

运行结果如下:

//定时发送每字节的数据:


/*
*  for linux
#include<stdio.h>
#include<stdlib.h>
#include<sys/time.h>
#include<unistd.h>
*/

//for windows
#include <windows.h>
#include <stdio.h>

#define u8  unsigned char
#define u16 unsigned short
#define u32 unsigned long
#define u64 unsigned long long


long g_sys_timestamp = 0;//系统时间戳,单位msec

long get_timestamp()
{
	/*
	struct timeval tv;
	gettimeofday(&tv, NULL);
	long sec = tv.tv_sec;
	static u64 init_ms = 0;
	u64 curr_ms = sec * 1000 + tv.tv_usec / 1000;
	if (init_ms == 0)
	{
		init_ms = curr_ms;
	}
	return (long)(curr_ms - init_ms);*/

	static u64 init_ms = 0;
	if (init_ms == 0)
	{
		init_ms = GetTickCount();
	}
	return (GetTickCount()- init_ms);

}


void msleep(int ms)
{
	//usleep(1000 * ms);
	Sleep(ms);
}


//=============================================
#define MAX_SEND_LEN 10

u8 g_sendBuffer1[MAX_SEND_LEN] = { 0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa };
u8 g_sendBuffer2[MAX_SEND_LEN] = { 0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba };


//模拟单片机发送单字符
void UART_Send_Byte(u8 ch)
{
	//TODO user code...
	static long old_tick = 0;
	printf("[%d]SEND=%02X.\n", g_sys_timestamp, ch);
	printf("Curr=%d,old=%d.take=(%d)ms.\n", g_sys_timestamp, old_tick, g_sys_timestamp - old_tick);
	old_tick = g_sys_timestamp;
}

// call_interval_set :每隔N ms调用1次串口发送
int timer_send_uart(u8* data, int delaycnt, const int call_interval_set)
{
	static long old_tick = 0;
	static int send_index = -1;
	static int send_delayCnt = 0;

	if (g_sys_timestamp < old_tick + call_interval_set)
	{
		return send_index;
	}

	old_tick = g_sys_timestamp;

	//TODO timer process here:
	send_index++;
	if (send_index == 0)
	{
		send_delayCnt = delaycnt;
	}
	else if (send_index >= MAX_SEND_LEN)
	{
		if (--send_delayCnt <= 0)
		{
			send_index = -1;
			send_delayCnt = delaycnt;
			return 0xFF;//finish signal
		}
		else
			return send_index;
	}
	UART_Send_Byte(data[send_index]);
	return send_index;
}

//在循环中定时发送数据处理 

int main(int argc, char** argv)
{
	printf("=======C_BuildTime=[%s]==============\r\n\r\n", __TIME__);

	int ret_index = 0;

	while (1)
	{
		//假设这个变量是在中断每1ms自增的时间戳
		//注意:long为4字节,时间最大值达到1193小时
		g_sys_timestamp = get_timestamp();

		ret_index = timer_send_uart(g_sendBuffer1, 5, 1000);//目的:做到每个数据定时发送

		msleep(5 + rand() % 5); //随机延时,模拟用户逻辑的随机性

		if (ret_index == 0xFF) //发送完第1组数据
			break;
	}
	printf("\n[%d]=======Finish!======\n", g_sys_timestamp);
	return 0;
}

定时运行效果如下:

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值