STM32F407串口操作

前言

一般的开发板,最多只能试验2到3个串口。开发板厂商也不可能将MCU上的所有资源都引出来给你用。
除非自己来做开发板,但是要花时间的。细节蛮多的。
一般除了和当前的工作任务相关,没有领导会安排带薪的时间来做这种验证性任务。

但是,如果硬件接口没有引出,写出的代码,就有些细节问题,无法验证。虽然说串口1到串口6的初始化和使用都是一样的,但是没有全部验证完,谁敢说自己写的没问题,能直接用到产品上呢。

产品板子上用STM32F407, 6对串口线都已经引出。
还是产品板子好,6个串口都能验证收发。
MCU的串口引脚转成485引出到面板接口, 用485转232头 + 232转USB串口, 接到PC端作为COM口.
在PC端,运行串口调试助手,配合在下位机中的串口发送和串口中断中下断点,就能知道每个串口收发是否正常了。

工程为MDK5 + STM32F407库函数版本 + ucOSII, 对6个串口都做了初始化,用中断方式操作。
6个串口通过一个232转485的接口板接到面板的6个485RJ45插座上. 因为485接口板是半双工,所以同一时间点,只能有一个串口发送或接收。在发送前,打开485发送使能,发送数据,如果要等回答,接着打开485接收使能,延时等回包,处理回包。因为485发送接收使能是6个串口共用一个,所以,用一个互斥量来使485发送接收,只能被一个串口使用。串口上接的设备是被动的,采用一问一答的方式。

demo下载点

已经在产品板子上试验过了,6个串口收发都好使。
test_stm32f407_all_uart_on_ucosII.zip

试验

假设硬件没问题(这是前提条件)。
如果写的程序,6个串口不能正常收发. 首先要看看串口的6对管脚是否选择错了(软件使用的串口管脚,一定要和原理图一致)。

串口号 发送引脚 接收引脚
串口1 PA9/PB6 PA10/PB7
串口2 PA2/PD5 PA3/PD6
串口3 PB10/PC10/PD8 PB11/PC11/PD9
串口4 PC10/PA0 PC11/PA1
串口5 PC12 PD2
串口6 PC6/PG14 PC7/PG9

检查NVIC, 看看是否设置正确。可以统一将NVIC设置的代码放到主函数中。等有问题时,方便统计检查。
设备的初始化工作,如果和ucOS无关,可以统一放到main函数中。如果和ucOS函数相关,可以放到开始任务中做。初始化的工作尽早做。

检查串口的初始化方式,是中断方式,还是DMA方式。GPIO初始化使能,设备初始化参数,设备使能,中断设置是否正确。
看看任务的优先级是否设置正确,是否让出了时间片给其他任务。
如果有公用的485使能,看485使能资源的独占是否正确。
看看是否因为任务调度函数使用不当,使发包后的延时函数不生效,导致发包没等回包。
每个串口的收发单独验证,是否每个串口任务都能重复多次执行到。是否每次回包都能重复多次收到。

调试中遇到的问题

仿真器无法进入main函数

要加入禁止半主机模式的代码

//////////////////////////////////////////////////////////////////
//加入以下代码,支持printf函数,而不需要选择use MicroLIB	  
// 如果不加如下代码, 仿真器进入不了main入口点
#if 1
#pragma import(__use_no_semihosting)             
// 标准库需要的支持函数                 
struct __FILE 
{ 
	int handle; 
}; 

FILE __stdout;

//定义_sys_exit()以避免使用半主机模式    
void _sys_exit(int x) 
{ 
	x = x; 
} 
//重定义fputc函数 
int fputc(int ch, FILE *f)
{ 	
	/*
	while((USART1->SR&0X40)==0);//循环发送,直到发送完毕   
	USART1->DR = (u8) ch;      
	*/
	return ch;
}
#endif
//支持printf的定义
//////////////////////////////////////////////////////////////////

用仿真器单步执行时,任何一句代码的操作都可能会挂掉(不返回)

做demo时,没实现SysTick_Handler, 所以ucOS任务调度有问题。

// systick中断服务函数,使用ucos时用到
// 这个函数必须有, 否则串口收发都不正常(调用串口收发时,会死掉, 执行一个GPIO操作,都会死掉,单步一下,仿真器就没响应了)
void SysTick_Handler(void)
{				   
	OSIntEnter(); // 进入中断
    OSTimeTick(); // 调用ucos的时钟服务程序
    OSIntExit(); // 触发任务切换软中断
}

防止库函数参数设置错

打开 assert_failed,在自己的assert_failed中做死循环,下断点,如果哪个库函数参数输入错误,就能马上发现。

void assert_failed(uint8_t* file, uint32_t line)
{
	// 这里就为断点能停下,然后返回, 看看,哪里参数设置错了
	while (0) {
	}
}

即时发现系统挂掉和系统重启

在程序入口点,HardFault_Handler(), SystemReset()处下断点,如果程序挂掉或跑飞,马上能发现。然后分析原因。

发包后,等不到本次回包

调度函数OSSchedLock()不能在发包前调用,这个函数调用后,OSTimeDlyHMSM()中的延时就失效了。
换用了互斥量解决。

OS_EVENT* g_osMutex_for_res_485; // 485收发操作资源的互斥量
// ...
   // MY_OS_MUTEX_PRIO 等级要稍高于所有用到互斥量的子任务优先级
	g_osMutex_for_res_485 = OSMutexCreate(MY_OS_MUTEX_PRIO, &err);
	if (NULL == g_osMutex_for_res_485) {
		printf("err : NULL == g_osMutex_for_res_485");
	}
// ...
		OSMutexPend(g_osMutex_for_res_485, 0, &err);
		test_uart1(); // 串口操作中可以有发包后的延时函数,等回包
		OSMutexPost(g_osMutex_for_res_485);

多个串口子任务,不是每个都执行到

这里有2个情况
case1:
ucOSII不支持多个优先级相同的任务进行时间片轮转,必须每个任务优先级不同
如果多个子任务的优先级相同,那只有第一个子任务会被重复执行,其他子任务一次都执行不到(或只能被执行一次).

// ucOSII不支持相同优先级任务的时间片轮转,所以每个任务的优先级必须不同

// 如果一个互斥量在多个任务中使用, 那么互斥量的任务优先级要略大于这些使用互斥量的任务优先级, 防止任务优先级反转

#define MY_OS_MUTEX_PRIO 23 // 互斥量的优先级

#define TASK_UART1_PRIO	24  // 串口任务
#define TASK_UART2_PRIO	25  // 串口任务
#define TASK_UART3_PRIO	26  // 串口任务
#define TASK_UART4_PRIO	27  // 串口任务
#define TASK_UART5_PRIO	28  // 串口任务
#define TASK_UART6_PRIO	29  // 串口任务

case2:
用到了互斥量之后,如果6个子任务总的逻辑执行时间大于每个任务让出时间片的时间,就会导致后面的任务执行不到。

void task_UART1(void *p_arg)
{
	INT8U err;
	
	// 不能调用OSSchedLock(), 会使延时函数失效
	// OSSchedLock(); // 停止任务调度
	// OSSchedUnlock(); // 开启任务调度
	while(1)
	{	
		OSMutexPend(g_osMutex_for_res_485, 0, &err);
		test_uart1();
		OSMutexPost(g_osMutex_for_res_485);

		// g_osMutex_for_res_485 只在6个串口任务中用
		// 如果每个串口任务的实际执行函数test_uartx()的总时间 > 下面的延时时间, 会导致不是每个串口任务都能被执行到
		// 所以下面的延时时间, 要大于6个串口任务执行的总时间
		// e.g. 每个串口执行函数的时间为600ms, 那6个串口执行的总时间就是600ms * 6 = 3.6s
		// 那么每个串口任务让出时间片的时间,就必须大于3.6s, 那让出时间片的时间最小为是4s, 否则后面低优先级的串口任务,执行不到
		
		// 实际测试,下面的让出时间片为3秒就可以,估计是ucOS延时不精确的原因
		// 但是,如果延时时间为2秒,低优先级的串口任务就执行不到了
		OSTimeDlyHMSM(0, 0, 4, 0); // 让出时间片, 防止由于使用了互斥量, 又没有禁止任务调度,防止低优先级的任务执行不到
	}
}

工程预览

测试工程为了测试STM32F407自带的6个串口。设计实现成:
每个串口一个ucOSII任务,每个任务中发包后,延时600ms等回包。
串口中断函数只是收包到缓冲区,尽量少干活。
发包+延时后,如果缓冲区内有回包,加上"\r\n"回发回去。清掉缓冲区计数。

// @file \Project\main.c

#include "includes.h" 

//////////////////////////////////////////////////////////////////
//加入以下代码,支持printf函数,而不需要选择use MicroLIB	  
// 如果不加如下代码, 仿真器进入不了main入口点
#if 1
#pragma import(__use_no_semihosting)             
// 标准库需要的支持函数                 
struct __FILE 
{ 
	int handle; 
}; 

FILE __stdout;

//定义_sys_exit()以避免使用半主机模式    
void _sys_exit(int x) 
{ 
	x = x; 
} 
//重定义fputc函数 
int fputc(int ch, FILE *f)
{ 	
	/*
	while((USART1->SR&0X40)==0);//循环发送,直到发送完毕   
	USART1->DR = (u8) ch;      
	*/
	return ch;
}
#endif
//支持printf的定义
//////////////////////////////////////////////////////////////////

// 如果没有通讯控制, 定义空宏
#define RS485_Tx                GPIO_SetBits(GPIOE, GPIO_Pin_9)
#define RS485_Rx                GPIO_ResetBits(GPIOE, GPIO_Pin_9)

// 因为6个串口通过一块232转485的半双工转接板,所以485的收发操作是要独占的(假设发送完成后,需要等回答)
// 那么RS485_Rx和延时函数之间的操作,就不允许有其他的任务执行RS485_Tx
// 这里弄一个互斥量对应485收发
OS_EVENT* g_osMutex_for_res_485; // 485收发操作资源的互斥量

// 串口参数
#define UART_BAUDRATE_DEFAULT 9600

#define UART1_BAUDRATE 9600
#define UART2_BAUDRATE 9600
#define UART3_BAUDRATE 9600
#define UART4_BAUDRATE 9600
#define UART5_BAUDRATE 9600
#define UART6_BAUDRATE 9600

// 任务等级

#define START_TASK_PRIO	11 // 开始任务

// ucOSII不支持相同优先级任务的时间片轮转,所以每个任务的优先级必须不同

// 如果一个互斥量在多个任务中使用, 那么互斥量的任务优先级要略大于这些使用互斥量的任务优先级
#define MY_OS_MUTEX_PRIO 23 // 互斥量的优先级

#define TASK_UART1_PRIO	24  // 串口任务
#define TASK_UART2_PRIO	25  // 串口任务
#define TASK_UART3_PRIO	26  // 串口任务
#define TASK_UART4_PRIO	27  // 串口任务
#define TASK_UART5_PRIO	28  // 串口任务
#define TASK_UART6_PRIO	29  // 串口任务

// 任务栈大小
#define START_STK_SIZE	128
#define TASK_UART_STACK_SIZE	128

// 任务栈
static OS_STK	Task_Stack_START[START_STK_SIZE]; // 任务堆栈 - 开始任务

static OS_STK	Task_Stack_UART1[TASK_UART_STACK_SIZE]; // 任务堆栈 - 串口1
static OS_STK	Task_Stack_UART2[TASK_UART_STACK_SIZE]; // 任务堆栈 - 串口2
static OS_STK	Task_Stack_UART3[TASK_UART_STACK_SIZE]; // 任务堆栈 - 串口3
static OS_STK	Task_Stack_UART4[TASK_UART_STACK_SIZE]; // 任务堆栈 - 串口4
static OS_STK	Task_Stack_UART5[TASK_UART_STACK_SIZE]; // 任务堆栈 - 串口5
static OS_STK	Task_Stack_UART6[TASK_UART_STACK_SIZE]; // 任务堆栈 - 串口6

// 任务函数
void start_task(void *p_arg); // 开始任务

void task_UART1(void *p_arg); // 串口任务
void task_UART2(void *p_arg);
void task_UART3(void *p_arg);
void task_UART4(void *p_arg);
void task_UART5(void *p_arg);
void task_UART6(void *p_arg);

// 初始化函数
void sys_clock_init(u8 SYSCLK);
void my_NVIC_init(void);
void rs485_init(void);
void uart_init1(void);
void uart_init2(void);
void uart_init3(void);
void uart_init4(void);
void uart_init5(void);
void uart_init6(void);
void set_uart_param(int i_uart_sn, USART_InitTypeDef* p_USART_InitStructure, int baudrate, int parity, int word_length, int stop_bits);

// 普通函数
void STM32_UART_SendDatas(int i_uart_index, const uint8_t *buf,unsigned short size);
void STM32_UART1_SendDatas(const uint8_t *buf,uint16_t size);
void STM32_UART2_SendDatas(const uint8_t *buf,uint16_t size);
void STM32_UART3_SendDatas(const uint8_t *buf,uint16_t size);
void STM32_UART4_SendDatas(const uint8_t *buf,uint16_t size);
void STM32_UART5_SendDatas(const uint8_t *buf,uint16_t size);
void STM32_UART6_SendDatas(const uint8_t *buf,uint16_t size);

void test_uart1(void);
void test_uart2(void);
void test_uart3(void);
void test_uart4(void);
void test_uart5(void);
void test_uart6(void);

int main(void)
{
	// 主函数只作一些必要的初始化操作
	SCB->VTOR = FLASH_BASE | 0; // 中断指针向量跳转, 向量表地址在0x08000000 
	sys_clock_init(168); // 系统时钟初始化(主频168MHZ)
	my_NVIC_init();
	rs485_init();
	uart_init1();
	uart_init2();
	uart_init3();
	uart_init4();
	uart_init5();
	uart_init6();
	
	OSInit(); // UCOS初始化
	// 因为用到了ucOS, 和任务调度,延时操作相关的操作都放到任务中去作
	OSTaskCreate(start_task,(void*)0, &Task_Stack_START[START_STK_SIZE - 1], START_TASK_PRIO); // 开始任务创建
	OSStart();
	return 0;
}

void start_task(void *p_arg)
{
	INT8U err;
	
	printf(">> start_task\n");
	
	// 初始化设备
	g_osMutex_for_res_485 = OSMutexCreate(MY_OS_MUTEX_PRIO, &err);
	if (NULL == g_osMutex_for_res_485) {
		printf("err : NULL == g_osMutex_for_res_485");
	}
	
	// 创建6个串口任务
	OSTaskCreate(task_UART1, 0, &Task_Stack_UART1[TASK_UART_STACK_SIZE - 1], TASK_UART1_PRIO); 
	OSTaskCreate(task_UART2, 0, &Task_Stack_UART2[TASK_UART_STACK_SIZE - 1], TASK_UART2_PRIO);
    OSTaskCreate(task_UART3, 0, &Task_Stack_UART3[TASK_UART_STACK_SIZE - 1], TASK_UART3_PRIO); 
    OSTaskCreate(task_UART4, 0, &Task_Stack_UART4[TASK_UART_STACK_SIZE - 1], TASK_UART4_PRIO); 
    OSTaskCreate(task_UART5, 0, &Task_Stack_UART5[TASK_UART_STACK_SIZE - 1], TASK_UART5_PRIO);
	OSTaskCreate(task_UART6, 0, &Task_Stack_UART6[TASK_UART_STACK_SIZE - 1], TASK_UART6_PRIO); 

	while(1)
	{
        OSTimeDlyHMSM(0,0,1,0); // 让出时间片
	}
}

void task_UART1(void *p_arg)
{
	INT8U err;
	
	// 不能调用OSSchedLock(), 会使延时函数失效
	// OSSchedLock(); // 停止任务调度
	// OSSchedUnlock(); // 开启任务调度
	while(1)
	{	
		OSMutexPend(g_osMutex_for_res_485, 0, &err);
		test_uart1();
		OSMutexPost(g_osMutex_for_res_485);

		// g_osMutex_for_res_485 只在6个串口任务中用
		// 如果每个串口任务的实际执行函数test_uartx()的总时间 > 下面的延时时间, 会导致不是每个串口任务都能被执行到
		// 所以下面的延时时间, 要大于6个串口任务执行的总时间
		// e.g. 每个串口执行函数的时间为600ms, 那6个串口执行的总时间就是600ms * 6 = 3.6s
		// 那么每个串口任务让出时间片的时间,就必须大于3.6s, 那让出时间片的时间最小为是4s, 否则后面低优先级的串口任务,执行不到
		
		// 实际测试,下面的让出时间片为3秒就可以,估计是ucOS延时不精确的原因
		// 但是,如果延时时间为2秒,低优先级的串口任务就执行不到了
		OSTimeDlyHMSM(0, 0, 4, 0); // 让出时间片, 防止由于使用了互斥量, 又没有禁止任务调度,防止低优先级的任务执行不到
	}
}

void task_UART2(void *p_arg)
{
	INT8U err;
	while(1)
	{	
		OSMutexPend(g_osMutex_for_res_485, 0, &err);
		test_uart2();
		OSMutexPost(g_osMutex_for_res_485);

		OSTimeDlyHMSM(0, 0, 4, 0); // 让出时间片, 防止由于使用了互斥量, 又没有禁止任务调度,防止低优先级的任务执行不到
	}
}

void task_UART3(void *p_arg)
{
	INT8U err;
	while(1)
	{	
		OSMutexPend(g_osMutex_for_res_485, 0, &err);
		test_uart3();
		OSMutexPost(g_osMutex_for_res_485);

		OSTimeDlyHMSM(0, 0, 4, 0); // 让出时间片, 防止由于使用了互斥量, 又没有禁止任务调度,防止低优先级的任务执行不到
	}
}

void task_UART4(void *p_arg)
{
	INT8U err;
	while(1)
	{	
		OSMutexPend(g_osMutex_for_res_485, 0, &err);
		test_uart4();
		OSMutexPost(g_osMutex_for_res_485);

		OSTimeDlyHMSM(0, 0, 4, 0); // 让出时间片, 防止由于使用了互斥量, 又没有禁止任务调度,防止低优先级的任务执行不到
	}
}

void task_UART5(void *p_arg)
{
	INT8U err;
	while(1)
	{	
		OSMutexPend(g_osMutex_for_res_485, 0, &err);
		test_uart5();
		OSMutexPost(g_osMutex_for_res_485);

		OSTimeDlyHMSM(0, 0, 4, 0); // 让出时间片, 防止由于使用了互斥量, 又没有禁止任务调度,防止低优先级的任务执行不到
	}
}

void task_UART6(void *p_arg)
{
	INT8U err;
	while(1)
	{	
		OSMutexPend(g_osMutex_for_res_485, 0, &err);
		test_uart6();
		OSMutexPost(g_osMutex_for_res_485);

		OSTimeDlyHMSM(0, 0, 4, 0); // 让出时间片, 防止由于使用了互斥量, 又没有禁止任务调度,防止低优先级的任务执行不到
	}
}

// systick中断服务函数,使用ucos时用到
// 这个函数必须有, 否则串口收发都不正常(调用串口收发时,会死掉, 执行一个GPIO操作,都会死掉,单步一下,仿真器就没响应了)
void SysTick_Handler(void)
{				   
	OSIntEnter(); // 进入中断
    OSTimeTick(); // 调用ucos的时钟服务程序
    OSIntExit(); // 触发任务切换软中断
}

void sys_clock_init(u8 SYSCLK)
{
#ifdef OS_CRITICAL_METHOD 	//如果OS_CRITICAL_METHOD定义了,说明使用ucosII了.
	u32 reload;
#endif
 	SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
	    
#ifdef OS_CRITICAL_METHOD 	//如果OS_CRITICAL_METHOD定义了,说明使用ucosII了.
	reload=SYSCLK/8;		//每秒钟的计数次数 单位为K	   
	reload*=1000000/OS_TICKS_PER_SEC;//根据OS_TICKS_PER_SEC设定溢出时间
							//reload为24位寄存器,最大值:16777216,在168M下,约合0.7989s左右	
	SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk;   	//开启SYSTICK中断
	SysTick->LOAD=reload; 	//每1/OS_TICKS_PER_SEC秒中断一次	
	SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk;   	//开启SYSTICK
#else
	fac_ms=(u16)fac_us*1000;//非ucos下,代表每个ms需要的systick时钟数   
#endif
		
}

void set_uart_param(int i_uart_sn, USART_InitTypeDef* p_USART_InitStructure, int baudrate, int parity, int word_length, int stop_bits) {
	if (NULL != p_USART_InitStructure) {
		p_USART_InitStructure->USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 无硬件数据流控制
		p_USART_InitStructure->USART_Mode = USART_Mode_Rx | USART_Mode_Tx; // 收发模式

		// 9600
		p_USART_InitStructure->USART_BaudRate = baudrate; // 比特率设定

		// N
		switch (parity) {
			case 0:
				p_USART_InitStructure->USART_Parity = USART_Parity_No; // 无校验
				break;
			case 1:
				p_USART_InitStructure->USART_Parity = USART_Parity_Odd; // 奇验位
				break;
			case 2:
				p_USART_InitStructure->USART_Parity = USART_Parity_Even; // 偶验位
				break;
			default:
				p_USART_InitStructure->USART_Parity = USART_Parity_No; // 无校验
				break;
		}
		
		switch (word_length) {
			case 8:
				p_USART_InitStructure->USART_WordLength = USART_WordLength_8b; // 8数据位长度	
				break;
			case 9:
				p_USART_InitStructure->USART_WordLength = USART_WordLength_9b; // 9数据位长度
				break;
			default:
				p_USART_InitStructure->USART_WordLength = USART_WordLength_8b; // 8数据位长度	
				break;
		}
		
		switch (stop_bits) {
			case 0:
				p_USART_InitStructure->USART_StopBits = USART_StopBits_1; // 1停止位
				break;
			case 1:
				p_USART_InitStructure->USART_StopBits = USART_StopBits_2; // 2停止位
				break;
			default:
				p_USART_InitStructure->USART_StopBits = USART_StopBits_1; // 1停止位
				break;
		}
	}
}

void my_NVIC_init(void)
{
	NVIC_InitTypeDef NVIC_InitStructure;
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 中断分组配置(2位抢占优先级, 2位子优先级, 优先级有效值范围 = (0 ~ 3))

	// 串口中断优先级设置 - COM1
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; // 串口中断通道
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; // 抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 响应优先级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // IRQ通道使能
	NVIC_Init(&NVIC_InitStructure); // 根据指定的参数初始化VIC寄存器、

	// 串口中断优先级设置 - COM2
	NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; // 串口中断通道
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; // 抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; // 响应优先级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // IRQ通道使能
	NVIC_Init(&NVIC_InitStructure); // 根据指定的参数初始化VIC寄存器、

	// 串口中断优先级设置 - COM3
	NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn; // 串口中断通道
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; // 抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; // 响应优先级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // IRQ通道使能
	NVIC_Init(&NVIC_InitStructure); // 根据指定的参数初始化VIC寄存器、

	// 串口中断优先级设置 - COM 4
	NVIC_InitStructure.NVIC_IRQChannel = UART4_IRQn; // 串口中断通道
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; // 抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; // 响应优先级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // IRQ通道使能
	NVIC_Init(&NVIC_InitStructure); // 根据指定的参数初始化VIC寄存器、

	// 串口中断优先级设置 - COM 5
	NVIC_InitStructure.NVIC_IRQChannel = UART5_IRQn; // 串口中断通道
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; // 抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 响应优先级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // IRQ通道使能
	NVIC_Init(&NVIC_InitStructure); // 根据指定的参数初始化VIC寄存器、

	// 串口中断优先级设置 - COM 6
	NVIC_InitStructure.NVIC_IRQChannel = USART6_IRQn; // 串口中断通道
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; // 抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; // 响应优先级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // IRQ通道使能
	NVIC_Init(&NVIC_InitStructure); // 根据指定的参数初始化VIC寄存器、
}

void rs485_init(void)
{
	// 6个串口都通过rs485转接板到后面板
	// rs485转接板是半双工, 发送和接收都需要切换方向
	// 每个串口操作时,其他串口要互斥
	
	GPIO_InitTypeDef GPIO_InitStructure;
	
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE,ENABLE); // 使能GPIOE的时钟

	// 485收发引脚初始化
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;// 输出
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;  // 推挽输出
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;  // 上拉
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; // 高速GPIO
	GPIO_Init(GPIOE,&GPIO_InitStructure);	
}

// 初始化IO - 串口1 
void uart_init1(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;

	// 使能串口管脚所在端口时钟, 使能串口时钟
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); // 使能GPIO时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); // 使能USART时钟
 
	// 串口引脚复用映射
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource9, GPIO_AF_USART1); // GPIOA9复用为USART1
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource10, GPIO_AF_USART1); // GPIOA10复用为USART1
	
	// 串口管脚参数设置
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; //GPIOA9与GPIOA10
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	//速度50MHz
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
	GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA9,PA10

    // USART通讯参数设置
	set_uart_param(1, &USART_InitStructure, UART1_BAUDRATE, 0, 8, 1);
	
	USART_Init(USART1, &USART_InitStructure); // 初始化串口
	USART_Cmd(USART1, ENABLE); // 使能串口
	
	// 开启串口中断(必须在使能串口后, 再开启串口中断, 否则不进串口中断处理函数)
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
	
	// 清发送完成标志
	while (USART_GetITStatus(USART1, USART_IT_TC) != RESET) {
		USART_ClearFlag(USART1, USART_FLAG_TC);
	}

	// 清接收完成标志
	while (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {
		USART_ClearFlag(USART1, USART_FLAG_RXNE);
	}
}

//初始化IO 串口2
void uart_init2(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	
	// 使能串口管脚所在端口时钟, 使能串口时钟
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD,ENABLE); //使能GPIO时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);//使能USART时钟
 
	//串口2对应引脚复用映射
	GPIO_PinAFConfig(GPIOD,GPIO_PinSource5,GPIO_AF_USART2); //GPIOD5复用为USART1
	GPIO_PinAFConfig(GPIOD,GPIO_PinSource6,GPIO_AF_USART2); //GPIOD6复用为USART1
	
	// USART2端口配置
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6; //GPIOD5与GPIOD6
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	//速度50MHz
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
	GPIO_Init(GPIOD,&GPIO_InitStructure);        //初始化PD5,PD6

	// 串口基本参数 初始化设置
	set_uart_param(2, &USART_InitStructure, UART2_BAUDRATE, 0, 8, 1);
	
    USART_Init(USART2, &USART_InitStructure); // 初始化串口
	USART_Cmd(USART2, ENABLE); // 使能串口
	
	// 开启串口中断(必须在使能串口后, 再开启串口中断, 否则不进串口中断处理函数)
	USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
	
	// 清发送完成标志
	while (USART_GetITStatus(USART2, USART_IT_TC) != RESET) {
		USART_ClearFlag(USART2, USART_FLAG_TC);
	}

	// 清接收完成标志
	while (USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) {
		USART_ClearFlag(USART2, USART_FLAG_RXNE);
	}
}

//初始化IO 串口3
//波特率默认9600
void uart_init3(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	
	// 使能串口管脚所在端口时钟, 使能串口时钟
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD,ENABLE); //使能GPIOD时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);//使能USART时钟
 
	//串口3对应引脚复用映射
	GPIO_PinAFConfig(GPIOD,GPIO_PinSource8,GPIO_AF_USART3); //GPIOD8复用为USART3
	GPIO_PinAFConfig(GPIOD,GPIO_PinSource9,GPIO_AF_USART3); //GPIOD9复用为USART3
	
	//USART3端口配置
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9; //GPIOD8与GPIOD9
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // 速度50MHz
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
	GPIO_Init(GPIOD,&GPIO_InitStructure);        //初始化GPIOD8, GPIOD9

	//串口基本参数 初始化设置
	set_uart_param(3, &USART_InitStructure, UART3_BAUDRATE, 0, 8, 1);
	
    USART_Init(USART3, &USART_InitStructure); //初始化串口3
	USART_Cmd(USART3, ENABLE);       //使能串口3 	
	
	// 开启串口中断(必须在使能串口后, 再开启串口中断, 否则不进串口中断处理函数)
	USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);
	
	// 清发送完成标志
	while (USART_GetITStatus(USART3, USART_IT_TC) != RESET) {
		USART_ClearFlag(USART3, USART_FLAG_TC);
	}

	// 清接收完成标志
	while (USART_GetITStatus(USART3, USART_IT_RXNE) != RESET) {
		USART_ClearFlag(USART3, USART_FLAG_RXNE);
	}
}

//初始化IO 串口4
//波特率默认9600
void uart_init4(void)
{
    //GPIO端口设置
    GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	
	// 使能串口管脚所在端口时钟, 使能串口时钟
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC,ENABLE); // 使能GPIO时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4,ENABLE); // 使能USART时钟
 
	// 串口引脚复用映射
	GPIO_PinAFConfig(GPIOC,GPIO_PinSource10,GPIO_AF_UART4); //GPIOC10复用为UART4
	GPIO_PinAFConfig(GPIOC,GPIO_PinSource11,GPIO_AF_UART4); //GPIOC11复用为UART4
	
	// 串口管脚参数设置
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11; //GPIOC10与GPIOC11
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	//速度50MHz
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
	GPIO_Init(GPIOC,&GPIO_InitStructure);        //初始化PC10,PC11

	//串口基本参数 初始化设置
	set_uart_param(4, &USART_InitStructure, UART4_BAUDRATE, 0, 8, 1);
	
    USART_Init(UART4, &USART_InitStructure); //初始化串口4
	USART_Cmd(UART4, ENABLE);       //使能串口4 	
	
	// 开启串口中断(必须在使能串口后, 再开启串口中断, 否则不进串口中断处理函数)
	USART_ITConfig(UART4, USART_IT_RXNE, ENABLE);
	
	// 清发送完成标志
	while (USART_GetITStatus(UART4, USART_IT_TC) != RESET) {
		USART_ClearFlag(UART4, USART_FLAG_TC);
	}

	// 清接收完成标志
	while (USART_GetITStatus(UART4, USART_IT_RXNE) != RESET) {
		USART_ClearFlag(UART4, USART_FLAG_RXNE);
	}
}

//初始化IO 串口5
//波特率默认9600
void uart_init5(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC,ENABLE); //使能GPIOC时钟
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD,ENABLE); //使能GPIOD时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART5,ENABLE); //使能USART5时钟
 
	//串口4对应引脚复用映射
	GPIO_PinAFConfig(GPIOC,GPIO_PinSource12,GPIO_AF_UART5); //GPIOC12复用为UART5
	GPIO_PinAFConfig(GPIOD,GPIO_PinSource2, GPIO_AF_UART5); //GPIOD2复用为UART5
	
	//UART5端口配置
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; //GPIOC12
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	//速度50MHz
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
	GPIO_Init(GPIOC,&GPIO_InitStructure);        //初始化PC12
	
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //GPIOD2
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	//速度50MHz
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
	GPIO_Init(GPIOD,&GPIO_InitStructure);        //初始化PD2	

	//串口基本参数 初始化设置
	set_uart_param(5, &USART_InitStructure, UART5_BAUDRATE, 0, 8, 1);

	USART_Init(UART5, &USART_InitStructure); //初始化串口5
	USART_Cmd(UART5, ENABLE);       //使能串口5 	
	
	// 开启串口中断(必须在使能串口后, 再开启串口中断, 否则不进串口中断处理函数)
	USART_ITConfig(UART5, USART_IT_RXNE, ENABLE);
	
	// 清发送完成标志
	while (USART_GetITStatus(UART5, USART_IT_TC) != RESET) {
		USART_ClearFlag(UART5, USART_FLAG_TC);
	}

	// 清接收完成标志
	while (USART_GetITStatus(UART5, USART_IT_RXNE) != RESET) {
		USART_ClearFlag(UART5, USART_FLAG_RXNE);
	}
}

//初始化IO 串口6
void uart_init6(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	
	// 使能串口管脚所在端口时钟, 使能串口时钟
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC,ENABLE); //使能GPIOD时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART6,ENABLE);//使能USART2时钟
 
	// 串口引脚复用映射
	GPIO_PinAFConfig(GPIOC,GPIO_PinSource6,GPIO_AF_USART6); //GPIOC6复用为USART6
	GPIO_PinAFConfig(GPIOC,GPIO_PinSource7,GPIO_AF_USART6); //GPIOC7复用为USART6
	
	//USART2端口配置
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; // GPIOC6与GPIOC7
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	//速度50MHz
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
	GPIO_Init(GPIOC,&GPIO_InitStructure);        //初始化PC6,PC7

	//串口基本参数 初始化设置
	set_uart_param(6, &USART_InitStructure, UART6_BAUDRATE, 0, 8, 1);

	USART_Init(USART6, &USART_InitStructure); //初始化串口6
	USART_Cmd(USART6, ENABLE);       //使能串口6	
	
	// 开启串口中断(必须在使能串口后, 再开启串口中断, 否则不进串口中断处理函数)
	USART_ITConfig(USART6, USART_IT_RXNE, ENABLE);
	
	// 清发送完成标志
	while (USART_GetITStatus(USART6, USART_IT_TC) != RESET) {
		USART_ClearFlag(USART6, USART_FLAG_TC);
	}

	// 清接收完成标志
	while (USART_GetITStatus(USART6, USART_IT_RXNE) != RESET) {
		USART_ClearFlag(USART6, USART_FLAG_RXNE);
	}
}

void STM32_UART1_SendDatas(const uint8_t *buf,uint16_t size)
{
	uint16_t i;
	RS485_Tx; // RS485-发送使能	
	for(i=0; i<size; i++)
	{
		// USART_ClearFlag(USART1,USART_FLAG_TC);
		USART_SendData(USART1, *(buf+i));
	    while (USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET)
		{
		}
	}
	RS485_Rx; // RS485-接收使能	 
}

void STM32_UART2_SendDatas(const uint8_t *buf,uint16_t size)
{
	uint16_t i;
	RS485_Tx; // RS485-发送使能	
	for(i=0; i<size; i++)
	{
		// USART_ClearFlag(USART2,USART_FLAG_TC);
		USART_SendData(USART2, *(buf+i));
	    while (USART_GetFlagStatus(USART2,USART_FLAG_TXE) == RESET)
		{
		}
	} 
	RS485_Rx; // RS485-接收使能	 
}

void STM32_UART3_SendDatas(const uint8_t *buf,uint16_t size)
{
	uint16_t i;
	RS485_Tx; // RS485-发送使能	
	for(i=0; i<size; i++)
	{
		// USART_ClearFlag(USART3,USART_FLAG_TC);
		USART_SendData(USART3, *(buf+i));
	    while (USART_GetFlagStatus(USART3,USART_FLAG_TXE) == RESET)
		{
		}
	} 
	RS485_Rx; // RS485-接收使能	 
}

void STM32_UART4_SendDatas(const uint8_t *buf,uint16_t size)
{
	uint16_t i;
	RS485_Tx; // RS485-发送使能	
	for(i=0; i<size; i++)
	{
		// USART_ClearFlag(UART4,USART_FLAG_TC);
		USART_SendData(UART4, *(buf+i));
	    while (USART_GetFlagStatus(UART4,USART_FLAG_TXE) == RESET)
		{
		}
	} 
	RS485_Rx; // RS485-接收使能	 
}

void STM32_UART5_SendDatas(const uint8_t *buf,uint16_t size)
{
	uint16_t i;
	RS485_Tx; // RS485-发送使能	
	for(i=0; i<size; i++)
	{
		// USART_ClearFlag(UART5,USART_FLAG_TC);
		USART_SendData(UART5, *(buf+i));
	    while (USART_GetFlagStatus(UART5,USART_FLAG_TXE) == RESET)
		{
		}
	} 
	RS485_Rx; // RS485-接收使能	 
}

void STM32_UART6_SendDatas(const uint8_t *buf,uint16_t size)
{
	uint16_t i;
	RS485_Tx; // RS485-发送使能	
	for(i=0; i<size; i++)
	{
		// USART_ClearFlag(USART6,USART_FLAG_TC);
		USART_SendData(USART6, *(buf+i));
	    while (USART_GetFlagStatus(USART6,USART_FLAG_TXE) == RESET)
		{
		}
	} 
	RS485_Rx; // RS485-接收使能	 
}

void STM32_UART_SendDatas(int i_uart_index, const uint8_t *buf,unsigned short size)
{
	switch (i_uart_index) {
		case TRANS_INDEX_UART1:
			STM32_UART1_SendDatas(buf, size);
			break;
		case TRANS_INDEX_UART2:
			STM32_UART2_SendDatas(buf, size);
			break;
		case TRANS_INDEX_UART3:
			STM32_UART3_SendDatas(buf, size);
			break;
		case TRANS_INDEX_UART4:
			STM32_UART4_SendDatas(buf, size);
			break;
		case TRANS_INDEX_UART5:
			STM32_UART5_SendDatas(buf, size);
			break;
		case TRANS_INDEX_UART6:
			STM32_UART6_SendDatas(buf, size);
			break;
		default:
			break;
	}
}

void test_uart1(void)
{
	int i = 0;
	uint8_t Size = 8;
	
	for (i = 0; i < Size; i++) {
		uart_send_buf[TRANS_INDEX_UART1][i] = 0x10 + i;
	}
	
	uart_send_buf[TRANS_INDEX_UART1][Size - 2] = '\r';
	uart_send_buf[TRANS_INDEX_UART1][Size - 1] = '\n';
	
	STM32_UART_SendDatas(TRANS_INDEX_UART1, (const uint8_t*)uart_send_buf[TRANS_INDEX_UART1], Size);
	
	// OSSchedLock(); // 停止任务调度
	// OSSchedUnlock(); // 开启任务调度
	// 当调用 OSSchedLock()时, 延时函数OSTimeDlyHMSM()就失效了, 会马上返回,不延时
	// 所以, 如果需要延时,就不能在OSSchedLock()之后调用

	OSTimeDlyHMSM(0, 0, 0, 600); // delay
	if (uart_recv_len[TRANS_INDEX_UART1] >= 4) {
		memcpy(uart_send_buf[TRANS_INDEX_UART1], uart_recv_buf[TRANS_INDEX_UART1], uart_recv_len[TRANS_INDEX_UART1]);
		Size = uart_recv_len[TRANS_INDEX_UART1] + 2;
		uart_send_buf[TRANS_INDEX_UART1][Size - 2] = '\r';
		uart_send_buf[TRANS_INDEX_UART1][Size - 1] = '\n';
		STM32_UART_SendDatas(TRANS_INDEX_UART1, (const uint8_t*)uart_send_buf[TRANS_INDEX_UART1], Size);
		uart_recv_len[TRANS_INDEX_UART1] = 0;
	}
}

void test_uart2(void)
{
	int i = 0;
	uint8_t Size = 8;
	
	for (i = 0; i < Size; i++) {
		uart_send_buf[TRANS_INDEX_UART2][i] = 0x20 + i;
	}
	
	uart_send_buf[TRANS_INDEX_UART2][Size - 2] = '\r';
	uart_send_buf[TRANS_INDEX_UART2][Size - 1] = '\n';
	
	STM32_UART_SendDatas(TRANS_INDEX_UART2, (const uint8_t*)uart_send_buf[TRANS_INDEX_UART2], Size);
	OSTimeDlyHMSM(0, 0, 0, 600); // delay
	if (uart_recv_len[TRANS_INDEX_UART2] >= 4) {
		memcpy(uart_send_buf[TRANS_INDEX_UART2], uart_recv_buf[TRANS_INDEX_UART2], uart_recv_len[TRANS_INDEX_UART2]);
		Size = uart_recv_len[TRANS_INDEX_UART2] + 2;
		uart_send_buf[TRANS_INDEX_UART2][Size - 2] = '\r';
		uart_send_buf[TRANS_INDEX_UART2][Size - 1] = '\n';
		STM32_UART_SendDatas(TRANS_INDEX_UART2, (const uint8_t*)uart_send_buf[TRANS_INDEX_UART2], Size);
		uart_recv_len[TRANS_INDEX_UART2] = 0;
	}
}

void test_uart3(void)
{
	int i = 0;
	uint8_t Size = 8;
	
	for (i = 0; i < Size; i++) {
		uart_send_buf[TRANS_INDEX_UART3][i] = 0x30 + i;
	}
	
	uart_send_buf[TRANS_INDEX_UART3][Size - 2] = '\r';
	uart_send_buf[TRANS_INDEX_UART3][Size - 1] = '\n';
	
	STM32_UART_SendDatas(TRANS_INDEX_UART3, (const uint8_t*)uart_send_buf[TRANS_INDEX_UART3], Size);
	OSTimeDlyHMSM(0, 0, 0, 600); // delay
	if (uart_recv_len[TRANS_INDEX_UART3] >= 4) {
		memcpy(uart_send_buf[TRANS_INDEX_UART3], uart_recv_buf[TRANS_INDEX_UART3], uart_recv_len[TRANS_INDEX_UART3]);
		Size = uart_recv_len[TRANS_INDEX_UART3] + 2;
		uart_send_buf[TRANS_INDEX_UART3][Size - 2] = '\r';
		uart_send_buf[TRANS_INDEX_UART3][Size - 1] = '\n';
		STM32_UART_SendDatas(TRANS_INDEX_UART3, (const uint8_t*)uart_send_buf[TRANS_INDEX_UART3], Size);
		uart_recv_len[TRANS_INDEX_UART3] = 0;
	}
}

void test_uart4(void)
{
	int i = 0;
	uint8_t Size = 8;
	
	for (i = 0; i < Size; i++) {
		uart_send_buf[TRANS_INDEX_UART4][i] = 0x40 + i;
	}
	
	uart_send_buf[TRANS_INDEX_UART4][Size - 2] = '\r';
	uart_send_buf[TRANS_INDEX_UART4][Size - 1] = '\n';
	
	STM32_UART_SendDatas(TRANS_INDEX_UART4, (const uint8_t*)uart_send_buf[TRANS_INDEX_UART4], Size);
	OSTimeDlyHMSM(0, 0, 0, 600); // delay
	if (uart_recv_len[TRANS_INDEX_UART4] >= 4) {
		memcpy(uart_send_buf[TRANS_INDEX_UART4], uart_recv_buf[TRANS_INDEX_UART4], uart_recv_len[TRANS_INDEX_UART4]);
		Size = uart_recv_len[TRANS_INDEX_UART4] + 2;
		uart_send_buf[TRANS_INDEX_UART4][Size - 2] = '\r';
		uart_send_buf[TRANS_INDEX_UART4][Size - 1] = '\n';
		STM32_UART_SendDatas(TRANS_INDEX_UART4, (const uint8_t*)uart_send_buf[TRANS_INDEX_UART4], Size);
		uart_recv_len[TRANS_INDEX_UART4] = 0;
	}
}

void test_uart5(void)
{
	int i = 0;
	uint8_t Size = 8;
	
	for (i = 0; i < Size; i++) {
		uart_send_buf[TRANS_INDEX_UART5][i] = 0x50 + i;
	}
	
	uart_send_buf[TRANS_INDEX_UART5][Size - 2] = '\r';
	uart_send_buf[TRANS_INDEX_UART5][Size - 1] = '\n';
	
	STM32_UART_SendDatas(TRANS_INDEX_UART5, (const uint8_t*)uart_send_buf[TRANS_INDEX_UART5], Size);
	OSTimeDlyHMSM(0, 0, 0, 600); // delay
	if (uart_recv_len[TRANS_INDEX_UART5] >= 4) {
		memcpy(uart_send_buf[TRANS_INDEX_UART5], uart_recv_buf[TRANS_INDEX_UART5], uart_recv_len[TRANS_INDEX_UART5]);
		Size = uart_recv_len[TRANS_INDEX_UART5] + 2;
		uart_send_buf[TRANS_INDEX_UART5][Size - 2] = '\r';
		uart_send_buf[TRANS_INDEX_UART5][Size - 1] = '\n';
		STM32_UART_SendDatas(TRANS_INDEX_UART5, (const uint8_t*)uart_send_buf[TRANS_INDEX_UART5], Size);
		uart_recv_len[TRANS_INDEX_UART5] = 0;
	}
}

void test_uart6(void)
{
	int i = 0;
	uint8_t Size = 8;
	
	for (i = 0; i < Size; i++) {
		uart_send_buf[TRANS_INDEX_UART6][i] = 0x60 + i;
	}
	
	uart_send_buf[TRANS_INDEX_UART6][Size - 2] = '\r';
	uart_send_buf[TRANS_INDEX_UART6][Size - 1] = '\n';
	
	STM32_UART_SendDatas(TRANS_INDEX_UART6, (const uint8_t*)uart_send_buf[TRANS_INDEX_UART6], Size);
	OSTimeDlyHMSM(0, 0, 0, 600); // delay
	if (uart_recv_len[TRANS_INDEX_UART6] >= 4) {
		memcpy(uart_send_buf[TRANS_INDEX_UART6], uart_recv_buf[TRANS_INDEX_UART6], uart_recv_len[TRANS_INDEX_UART6]);
		Size = uart_recv_len[TRANS_INDEX_UART6] + 2;
		uart_send_buf[TRANS_INDEX_UART6][Size - 2] = '\r';
		uart_send_buf[TRANS_INDEX_UART6][Size - 1] = '\n';
		STM32_UART_SendDatas(TRANS_INDEX_UART6, (const uint8_t*)uart_send_buf[TRANS_INDEX_UART6], Size);
		uart_recv_len[TRANS_INDEX_UART6] = 0;
	}
}

/**
  ******************************************************************************
  * @file    Project/STM32F4xx_StdPeriph_Templates/stm32f4xx_it.c 
  * @author  MCD Application Team
  * @version V1.4.0
  * @date    04-August-2014
  * @brief   Main Interrupt Service Routines.
  *          This file provides template for all exceptions handler and 
  *          peripherals interrupt service routine.
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; COPYRIGHT 2014 STMicroelectronics</center></h2>
  *
  * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
  * You may not use this file except in compliance with the License.
  * You may obtain a copy of the License at:
  *
  *        http://www.st.com/software_license_agreement_liberty_v2
  *
  * Unless required by applicable law or agreed to in writing, software 
  * distributed under the License is distributed on an "AS IS" BASIS, 
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx_it.h"
#include "includes.h"

unsigned int  uart_recv_len[UART_PORT_NUM]; // 统计出的串口接收数据长度
unsigned char uart_recv_buf[UART_PORT_NUM][NET_UART_BUF_LEN]; // 收到的串口数据
unsigned char uart_send_buf[UART_PORT_NUM][NET_UART_BUF_LEN]; // 发送的串口数据

__asm void SystemReset(void)
{
	MOV R0, #1           	//; 这里可以下断点, 好使
	MSR FAULTMASK, R0    	//; 清除FAULTMASK 禁止一切中断产生
	LDR R0, =0xE000ED0C  	//;
	LDR R1, =0x05FA0004  	//; 
	STR R1, [R0]         	//; 系统软件复位   
deadloop
    B deadloop        		//; 死循环使程序运行不到下面的代码
}

/** @addtogroup Template_Project
  * @{
  */

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

/******************************************************************************/
/*            Cortex-M4 Processor Exceptions Handlers                         */
/******************************************************************************/

/**
  * @brief  This function handles NMI exception.
  * @param  None
  * @retval None
  */
void NMI_Handler(void)
{
}

void assert_failed(uint8_t* file, uint32_t line)
{
	// 这里就为断点能停下,然后返回, 看看,哪里参数设置错了
	while (0) {
	}
}

/**
  * @brief  This function handles Hard Fault exception.
  * @param  None
  * @retval None
  */
void HardFault_Handler(void)
{
  /* Go to infinite loop when Hard Fault exception occurs */
  while (1)
  {
	  SystemReset();	   						//复位 
  }
}

/**
  * @brief  This function handles Memory Manage exception.
  * @param  None
  * @retval None
  */
void MemManage_Handler(void)
{
  /* Go to infinite loop when Memory Manage exception occurs */
  while (1)
  {
  }
}

/**
  * @brief  This function handles Bus Fault exception.
  * @param  None
  * @retval None
  */
void BusFault_Handler(void)
{
  /* Go to infinite loop when Bus Fault exception occurs */
  while (1)
  {
  }
}

/**
  * @brief  This function handles Usage Fault exception.
  * @param  None
  * @retval None
  */
void UsageFault_Handler(void)
{
  /* Go to infinite loop when Usage Fault exception occurs */
  while (1)
  {
  }
}

/**
  * @brief  This function handles SVCall exception.
  * @param  None
  * @retval None
  */
//void SVC_Handler(void)
//{
//}

/**
  * @brief  This function handles Debug Monitor exception.
  * @param  None
  * @retval None
  */
void DebugMon_Handler(void)
{
}

/**
  * @brief  This function handles PendSVC exception.
  * @param  None
  * @retval None
  */
//void PendSV_Handler(void)
//{
//}

/**
  * @brief  This function handles SysTick Handler.
  * @param  None
  * @retval None
  */
//void SysTick_Handler(void)
//{
//	OS_CPU_SR  cpu_sr;


//    OS_ENTER_CRITICAL();                         /* Tell uC/OS-II that we are starting an ISR          */
//    OSIntNesting++;
//    OS_EXIT_CRITICAL();

//    OSTimeTick();                                /* Call uC/OS-II's OSTimeTick()                       */

//    OSIntExit();                                 /* Tell uC/OS-II that we are leaving the ISR          */ 
//}

/******************************************************************************/
/*                 STM32F4xx Peripherals Interrupt Handlers                   */
/*  Add here the Interrupt Handler for the used peripheral(s) (PPP), for the  */
/*  available peripheral interrupt handler's name please refer to the startup */
/*  file (startup_stm32f4xx.s).                                               */
/******************************************************************************/

/**
  * @brief  This function handles PPP interrupt request.
  * @param  None
  * @retval None
  */
/*void PPP_IRQHandler(void)
{
}*/

void uart1_rx_to_buf(u8 uc_rx)
{
	int i_rx_buf_len = (int)sizeof(uart_recv_buf[TRANS_INDEX_UART1]);
	
	// 这里只能向缓冲区中丢接收到的字节内容,不能浪费时间作其他事情,否则引起接收丢包
	// uart_recv_len[TRANS_INDEX_UART1]
	if (0 == uart_recv_len[TRANS_INDEX_UART1]) {
		memset(uart_recv_buf[TRANS_INDEX_UART1], 0, i_rx_buf_len);
	}
	
	// 这里只管接收, 如果缓冲区满了, 就不向缓冲区存了
	// 等有人处理了缓冲区的数据, 将缓冲区的内容拿走了, 再向缓冲区内存
	if (uart_recv_len[TRANS_INDEX_UART1] < i_rx_buf_len) {
		uart_recv_buf[TRANS_INDEX_UART1][uart_recv_len[TRANS_INDEX_UART1] % (i_rx_buf_len - 1)] = uc_rx;
		uart_recv_len[TRANS_INDEX_UART1] ++;
	}
}

void uart2_rx_to_buf(u8 uc_rx)
{
	int i_rx_buf_len = (int)sizeof(uart_recv_buf[TRANS_INDEX_UART2]);
	
	if (0 == uart_recv_len[TRANS_INDEX_UART2]) {
		memset(uart_recv_buf[TRANS_INDEX_UART2], 0, i_rx_buf_len);
	}
	
	if (uart_recv_len[TRANS_INDEX_UART2] < i_rx_buf_len) {
		uart_recv_buf[TRANS_INDEX_UART2][uart_recv_len[TRANS_INDEX_UART2] % (i_rx_buf_len - 1)] = uc_rx;
		uart_recv_len[TRANS_INDEX_UART2] ++;
	}
}

void uart3_rx_to_buf(u8 uc_rx)
{
	int i_rx_buf_len = (int)sizeof(uart_recv_buf[TRANS_INDEX_UART3]);
	
	if (0 == uart_recv_len[TRANS_INDEX_UART3]) {
		memset(uart_recv_buf[TRANS_INDEX_UART3], 0, i_rx_buf_len);
	}
	
	if (uart_recv_len[TRANS_INDEX_UART3] < i_rx_buf_len) {
		uart_recv_buf[TRANS_INDEX_UART3][uart_recv_len[TRANS_INDEX_UART3] % (i_rx_buf_len - 1)] = uc_rx;
		uart_recv_len[TRANS_INDEX_UART3] ++;
	}
}

void uart4_rx_to_buf(u8 uc_rx)
{
	int i_rx_buf_len = (int)sizeof(uart_recv_buf[TRANS_INDEX_UART4]);
	
	if (0 == uart_recv_len[TRANS_INDEX_UART4]) {
		memset(uart_recv_buf[TRANS_INDEX_UART4], 0, i_rx_buf_len);
	}
	
	if (uart_recv_len[TRANS_INDEX_UART4] < i_rx_buf_len) {
		uart_recv_buf[TRANS_INDEX_UART4][uart_recv_len[TRANS_INDEX_UART4] % (i_rx_buf_len - 1)] = uc_rx;
		uart_recv_len[TRANS_INDEX_UART4] ++;
	}
}

void uart5_rx_to_buf(u8 uc_rx)
{
	int i_rx_buf_len = (int)sizeof(uart_recv_buf[TRANS_INDEX_UART5]);
	
	if (0 == uart_recv_len[TRANS_INDEX_UART5]) {
		memset(uart_recv_buf[TRANS_INDEX_UART5], 0, i_rx_buf_len);
	}
	
	if (uart_recv_len[TRANS_INDEX_UART5] < i_rx_buf_len) {
		uart_recv_buf[TRANS_INDEX_UART5][uart_recv_len[TRANS_INDEX_UART5] % (i_rx_buf_len - 1)] = uc_rx;
		uart_recv_len[TRANS_INDEX_UART5] ++;
	}
}

void uart6_rx_to_buf(u8 uc_rx)
{
	int i_rx_buf_len = (int)sizeof(uart_recv_buf[TRANS_INDEX_UART6]);
	
	if (0 == uart_recv_len[TRANS_INDEX_UART6]) {
		memset(uart_recv_buf[TRANS_INDEX_UART6], 0, i_rx_buf_len);
	}
	
	if (uart_recv_len[TRANS_INDEX_UART6] < i_rx_buf_len) {
		uart_recv_buf[TRANS_INDEX_UART6][uart_recv_len[TRANS_INDEX_UART6] % (i_rx_buf_len - 1)] = uc_rx;
		uart_recv_len[TRANS_INDEX_UART6] ++;
	}
}

void USART1_IRQHandler(void) // 串口1中断服务程序
{
	u8 uc_rx = 0;
	
	OSIntEnter();    
	
	if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
	{
		// 接收中断
		uc_rx =USART_ReceiveData(USART1); // 读取接收到的数据
		uart1_rx_to_buf(uc_rx);
		USART_ClearFlag(USART1, USART_FLAG_RXNE);
	} 
	
	OSIntExit(); // 退出中断
} 

void USART2_IRQHandler(void)
{
	u8 uc_rx = 0;
	
	OSIntEnter();    
	
	if (USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
	{
		uc_rx =USART_ReceiveData(USART2);
		uart2_rx_to_buf(uc_rx);
		USART_ClearFlag(USART2, USART_FLAG_RXNE);
	} 
	
	OSIntExit();
}

void USART3_IRQHandler(void)
{
	u8 uc_rx = 0;
	
	OSIntEnter();    
	
	if (USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)
	{
		uc_rx =USART_ReceiveData(USART3);
		uart3_rx_to_buf(uc_rx);
		USART_ClearFlag(USART3, USART_FLAG_RXNE);
	} 
	
	OSIntExit();
}

void UART4_IRQHandler(void)
{
	u8 uc_rx = 0;
	
	OSIntEnter();    
	
	if (USART_GetITStatus(UART4, USART_IT_RXNE) != RESET)
	{
		uc_rx =USART_ReceiveData(UART4);
		uart4_rx_to_buf(uc_rx);
		USART_ClearFlag(UART4, USART_FLAG_RXNE);
	} 
	
	OSIntExit();
}

void UART5_IRQHandler(void)
{
	u8 uc_rx = 0;
	
	OSIntEnter();    
	
	if (USART_GetITStatus(UART5, USART_IT_RXNE) != RESET)
	{
		uc_rx =USART_ReceiveData(UART5);
		uart5_rx_to_buf(uc_rx);
		USART_ClearFlag(UART5, USART_FLAG_RXNE);
	} 
	
	OSIntExit();
}

void USART6_IRQHandler(void)
{
	u8 uc_rx = 0;
	
	OSIntEnter();    
	
	if (USART_GetITStatus(USART6, USART_IT_RXNE) != RESET)
	{
		uc_rx =USART_ReceiveData(USART6);
		uart6_rx_to_buf(uc_rx);
		USART_ClearFlag(USART6, USART_FLAG_RXNE);
	} 
	
	OSIntExit();
}
/**
  * @}
  */ 


/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

发布了436 篇原创文章 · 获赞 126 · 访问量 175万+

猜你喜欢

转载自blog.csdn.net/LostSpeed/article/details/101562962