`
ydbc
  • 浏览: 718648 次
  • 性别: Icon_minigender_1
  • 来自: 大连
文章分类
社区版块
存档分类
最新评论

给android设备增加串口功能

 
阅读更多

给android设备增加串口功能


本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明.


环境:

主机:WIN7

开发环境:MDK4.23


功能:

打开Android手机或者平台的蓝牙,通过蓝牙连接蓝牙转串口板,通过蓝牙转串口板的串口与需要调试的串口设备相连


说明:

1.PCB为我同学hunter绘制,他同时是stm32的高手,感谢他提供的支持.

2.制作了一个蓝牙转串口的板子,Android设备连接上这个板子,就相当于增加了一个串口.

3.单片机选用的是STM32F101C8,蓝牙模块选用的是HC05.HC05本身就是一个蓝牙转串口模块,再增加一个单片机的作用是可以通过单片机来配置波特率等参数.

4.蓝牙转串口板可以用MINI USB来供电,或者用3.7V锂电池来供电,板子上带有充电管理芯片,由于没锂电池,充电这块还没有测试.

5.上位机程序(Android上的串口助手)暂时没有时间写,可以在安卓市场上搜索"蓝牙串口"下一个串口助手.

6.在上位机发送指定格式可以配置波特率,例:AT+BAUD9600END


实物图:



电路图:

第1部分:

图片较大,部分没有显示.可以在新窗口打开图片来看到全部内容

第2部分:


下位机程序:

public.h

#ifndef _PUBLIC_H_
#define _PUBLIC_H_

//公共头文件
#include "main.h"
#include "string.h"
#include "stdlib.h"
#include "stm32f10x_tim.h"

//宏定义
#define U8 unsigned char
#define U16 unsigned short
#define U32 unsigned long

//蓝牙转串口的缓存长度
#define LEN_BT_STACK 	10

//蓝牙波特率设置命令
#define BT_BAUD_4800	"AT+UART=4800,0,0"
#define BT_BAUD_9600   	"AT+UART=9600,0,0"
#define BT_BAUD_19200	"AT+UART=19200,0,0"
#define BT_BAUD_38400	"AT+UART=38400,0,0"
#define BT_BAUD_57600	"AT+UART=57600,0,0"
#define BT_BAUD_115200	"AT+UART=115200,0,0"
#define DEFAULT_BAUD	9600

//定义flash页大小
#if defined (STM32F10X_HD) || defined (STM32F10X_HD_VL) || (STM32F10X_CL) || defined (STM32F10X_XL)
  #define FLASH_PAGE_SIZE    ((uint16_t)0x800)
  #define FLASH_PAGES_TO_BE_PROTECTED (FLASH_WRProt_Pages12to13 | FLASH_WRProt_Pages14to15)  
#else
  #define FLASH_PAGE_SIZE    ((uint16_t)0x400)
  //需要关闭写保护的页面
  #define FLASH_PAGES_TO_BE_PROTECTED (FLASH_WRProt_Pages60to63)  
#endif

//定义操作的flash的始末地址63K-64K		
#define BANK1_WRITE_START_ADDR  ((uint32_t)0x0800FC00)
#define BANK1_WRITE_END_ADDR    ((uint32_t)0x08010000)

//数据结构

//通过蓝牙发过来的串口2的数据堆栈
//数据结构为循环队列,读写缓冲
#define LEN_BUF	512
struct _FIFO_Stack
{
	unsigned char buf[LEN_BUF];
	short ptr_r;
	short ptr_w;
};

//数据流式符合字符串头检索
#define LEN_MATCH_STRING_HEADER 9
struct _match_string_header
{
	char match[LEN_MATCH_STRING_HEADER];
	int state;
};

//数据流式符合字符串尾检索,并提取数据结构
#define LEN_MATCH_STRING_TAIL 3
struct _match_string_tail
{
	char match[LEN_MATCH_STRING_TAIL];
	int state;				//当前状态/下标
	int value;				//最后取得的值
	int max_len;			//数据最大长度
	char capture_string[10];
	int capture_index;		//当前捕获数据下标
	struct _match_string_header match_string_header;	//用来比较尾是否正确
	int flag;				//捕获数据状态或是捕获字符尾状态
};

//修改flash
struct _edit_flash
{
	unsigned short buf[512];
	int flag;		//判断flash是否被修改过
	int baud;		//需要写入/读出的波特率
};

//公共变量
//声明串口结构体
extern USART_InitTypeDef USART_InitStructure;

//声明FIFO堆栈给UART2使用
extern struct _FIFO_Stack fifo_uart2;

//声明FIFO堆栈给UART1使用
extern struct _FIFO_Stack fifo_uart1;

//声明修改flash结构体
extern struct _edit_flash edit_flash;

//公共函数
//按照蓝牙转串口的格式发送指令
void send_bt_cmd(char *str);

//循环缓冲方法
//初始化
void init_fifo_stack(struct _FIFO_Stack *stack);
//读取全部
//成功返回字节数,失败返回-1
short read_all_fifo_stack(struct _FIFO_Stack *stack,unsigned char *buf);
//写入1个字节
//失败返回-1,成功返回1
int write_byte_fifo_stack(struct _FIFO_Stack *stack,unsigned char byte);

//数据流式符合字符串头检索方法
//初始化
//成功返回1,失败返回0
int init_match_string_header(struct _match_string_header *m_str,char *buf);
//返回-1失败,返回0正在运行,返回1成功
int match_string_header_state(struct _match_string_header *m_str,char ch);

//数据流式符合字符串尾检索,并提取数据结构方法
//初始化
//成功返回1,失败返回0
int init_match_string_tail(struct _match_string_tail *m_str,char *buf,int max_len);
//返回-1失败,返回0正在运行,成功返回得到的数据
int match_string_tail_state(struct _match_string_tail *m_str,char ch);

//flash操作
//打开需要操作页面的写保护
void open_write_lock();
//向flash中写入数据,1024字节,512个半字
//成功返回写入的字节数,失败返回-1
int write_flash(unsigned short *buf);
//读取flash,读取1024字节,512半字
//成功返回读取的字节数,失败返回-1
int read_flash(unsigned short *buf);

//读取flash,获得flag和baud
//成功返回波特率,失败返回-1
int read_baud(struct _edit_flash *edit);
//写入波特率到flash
//成功返回1,失败返回0
int write_baud(struct _edit_flash *edit,int baud);

#endif


public.c:

#include "public.h"

//公共变量
//定义串口结构体
USART_InitTypeDef USART_InitStructure;

//声明FIFO堆栈给UART2使用
struct _FIFO_Stack fifo_uart2;

//声明FIFO堆栈给UART1使用
struct _FIFO_Stack fifo_uart1;

//声明修改flash结构体
struct _edit_flash edit_flash;

//按照蓝牙转串口的格式发送指令
void send_bt_cmd(char *str)
{
	while(*str != '\0')
	{
	 	USART_SendData(USART2,*str++); //发送一位数据
		while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET){} //等待字符发送完毕	
	}

	USART_SendData(USART2,'\r'); //发送一位数据
	while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET){} //等待字符发送完毕
	USART_SendData(USART2,'\n'); //发送一位数据
	while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET){} //等待字符发送完毕		
}

//循环缓冲方法
//初始化
void init_fifo_stack(struct _FIFO_Stack *stack)
{
	stack->ptr_r = 0;
	stack->ptr_w = 0;
	memset(stack->buf,0,LEN_BUF);
}

//读取全部
//成功返回字节数,失败返回0
short read_all_fifo_stack(struct _FIFO_Stack *stack,unsigned char *buf)
{
	short i = 0;
	short j = 0;
	short len = 0;
	short len2 = 0;

	//如果已经读完,则不读
	if (stack->ptr_r - stack->ptr_w == 0 || \
		stack->ptr_r - stack->ptr_w == -1)
	{
	 	return -1;
	}

	//如果读指针小于写指针
	if (stack->ptr_r < stack->ptr_w)
	{
		len =  stack->ptr_w - stack->ptr_r;
	 	for	(i = 0;i < len;i++)
		{
		   buf[i] = stack->buf[stack->ptr_r++];
		}
		return len;
	}
	else
	{
	 	//读指针大于写指针的情况
		len = (LEN_BUF - 1) - stack->ptr_r + 1;
		len2 = stack->ptr_w;
	   	for (i = 0;i < len;i++)
		{
		 	buf[j++] = stack->buf[stack->ptr_r++];	
		}
		stack->ptr_r = 0;
		for (i = 0;i < len2;i++)
		{
		 	buf[j++] = stack->buf[stack->ptr_r++];	
		}
		return (len + len2);
	}
}

//写入1个字节
//失败返回-1,成功返回1
int write_byte_fifo_stack(struct _FIFO_Stack *stack,unsigned char byte)
{
	//如果已经写完,则不写
	if (stack->ptr_w - stack->ptr_r == -1)
	{
	 	return -1;
	}

	stack->buf[stack->ptr_w++] = byte;

	//判断是否已经写满
	if (stack->ptr_w == LEN_BUF)
	{
	 	stack->ptr_w = 0;
	}
}

//数据流式符合字符串头检索方法
//初始化
//成功返回1,失败返回0
int init_match_string_header(struct _match_string_header *m_str,char *buf)
{
	int len = 0;
	int i = 0;
	
	len = strlen(buf);
	if (len > LEN_MATCH_STRING_HEADER)
	{
		return 0;
	}
	
	m_str->state = 0;
	for (i = 0;i < len;i++)
	{
		m_str->match[i] = buf[i];
	}
	m_str->match[i] = '\0';
	
	return 1;
}

//返回-1失败,返回0正在运行,返回1成功
int match_string_header_state(struct _match_string_header *m_str,char ch)
{
	if (ch == m_str->match[m_str->state])
	{
		m_str->state++;
		if (m_str->match[m_str->state] == '\0')
		{
			m_str->state = 0;
			
			return 1;
		}
		else
		{
			return 0;
		}
	}
	else
	{
		m_str->state = 0;
		
		return -1;
	}
}

//数据流式符合字符串尾检索,并提取数据结构方法
//初始化
//成功返回1,失败返回0
int init_match_string_tail(struct _match_string_tail *m_str,char *buf,int max_len)
{
	int len = 0;
	int i = 0;
	
	len = strlen(buf);
	if (len > LEN_MATCH_STRING_TAIL)
	{
		return 0;
	}
	
	m_str->state = 0;
	m_str->value = 0;
	m_str->max_len = max_len;
	m_str->capture_index = 0;
	m_str->flag = 0;
	for (i = 0;i < len;i++)
	{
		m_str->match[i] = buf[i];
	}
	m_str->match[i] = '\0';
	init_match_string_header(&(m_str->match_string_header),m_str->match);
	
	return 1;
}

//返回-1失败,返回0正在运行,成功返回得到的数据
int match_string_tail_state(struct _match_string_tail *m_str,char ch)
{
	int flag = 0;
	
	//判断是否捕获数据状态还是捕获字符尾状态
	if (m_str->flag || ch == 'E')
	{
		//捕获字符尾状态
		m_str->flag = 1;
		flag = match_string_header_state(&(m_str->match_string_header),ch);
		
		if (flag == -1)
		{
			//初始化数据
			m_str->state = 0;
			m_str->capture_index = 0;
			m_str->flag = 0;
		}
		
		if (flag == 1)
		{
			m_str->capture_string[m_str->capture_index] = '\0';
			m_str->value = atoi(m_str->capture_string);
			
			//初始化数据
			m_str->state = 0;
			m_str->capture_index = 0;
			m_str->flag = 0;
			
			return m_str->value;
		}
		
		return flag;
	}
	else
	{
		//捕获数据状态
		if (ch < '0' || ch > '9')
		{
			return -1;
		}
		
		//当已经达到最大数据长度且当前数据不是
		//当不是数据字符返回错误
		if (m_str->capture_index >= m_str->max_len)
		{
			m_str->state = 0;
			m_str->capture_index = 0;
			m_str->flag = 0;
			
			return -1;
		}
		else
		{
			m_str->capture_string[m_str->capture_index++] = ch;
			
			//如果达到最大长度,则置为捕获字符状态
			if (m_str->capture_index >= m_str->max_len)
			{
				m_str->flag = 1;
			}
			
			return 0;
		}
	}
}

//打开需要操作页面的写保护
void open_write_lock()
{
	uint32_t WRPR_Value = 0xFFFFFFFF, ProtectedPages = 0x0;
	volatile FLASH_Status FLASHStatus = FLASH_COMPLETE;

	//解锁flash控制器
	FLASH_Unlock();

	//得到所有已经被写保护的页面号,如果被写保护则置0,没有则置1
	WRPR_Value = FLASH_GetWriteProtectionOptionByte();

	//需要写保护的页面置1,不需要的置0
	ProtectedPages = ~(WRPR_Value | FLASH_PAGES_TO_BE_PROTECTED);
	
	//检查需要的页是否被写保护
	if((WRPR_Value | (~FLASH_PAGES_TO_BE_PROTECTED)) != 0xFFFFFFFF )
	{
		//擦除小信息模块,关闭写保护
		FLASHStatus = FLASH_EraseOptionBytes();
		
		//如果不是所有页面都需要打开写保护
		if(ProtectedPages != 0x0)
		{
		  //将其他页面置位写保护
		  FLASHStatus = FLASH_EnableWriteProtection(ProtectedPages);
		}
		//复位系统,重新载入小信息
		NVIC_SystemReset();
	}
}

//向flash中写入数据,1024字节,512个半字
//成功返回写入的字节数,失败返回-1
int write_flash(unsigned short *buf)
{
	uint32_t EraseCounter = 0x0,Address = 0x0;
	uint32_t WRPR_Value = 0xFFFFFFFF;
	uint32_t NbrOfPage;
	volatile FLASH_Status FLASHStatus = FLASH_COMPLETE;
	int i = 0;

	//得到需要操作的页面数
	NbrOfPage = (BANK1_WRITE_END_ADDR - BANK1_WRITE_START_ADDR) / FLASH_PAGE_SIZE;

	//得到所有已经被写保护的页面号,如果被写保护则置0,没有则置1
	WRPR_Value = FLASH_GetWriteProtectionOptionByte();
	
	//判断此页面是否被写保护,如果没有写保护则进行操作
	if ( (WRPR_Value & FLASH_PAGES_TO_BE_PROTECTED) != 0x00)
	{
		//清除所有等待标志位
		FLASH_ClearFlag(FLASH_FLAG_BSY | FLASH_FLAG_EOP|FLASH_FLAG_PGERR |FLASH_FLAG_WRPRTERR);	
		
		//擦数指定页面
		for(EraseCounter = 0; (EraseCounter < NbrOfPage) && (FLASHStatus == FLASH_COMPLETE); EraseCounter++)
		{
		 	FLASHStatus = FLASH_ErasePage(BANK1_WRITE_START_ADDR + (FLASH_PAGE_SIZE * EraseCounter));
		}
		
		//得到操作flash的起始地址
		Address = BANK1_WRITE_START_ADDR;
		//写flash,每次写2个字节
		while((Address < BANK1_WRITE_END_ADDR) && (FLASHStatus == FLASH_COMPLETE))
		{
			FLASHStatus = FLASH_ProgramHalfWord(Address, buf[i++]);
			Address = Address + 2;
		}

		return i;
	}
	else
	{ 
		return -1;
	}
}

//读取flash,读取1024字节,512半字
//成功返回读取的字节数,失败返回-1
int read_flash(unsigned short *buf)
{
	uint32_t Address = 0x0;
	int i = 0;

	//得到操作flash的起始地址
	Address = BANK1_WRITE_START_ADDR;
	//读flash,每次读两个字节
	while((Address < BANK1_WRITE_END_ADDR))
	{
		buf[i++] = *(__IO uint16_t*) Address;
		Address += 2;
	}

	return i;
}

//修改flash结构的方法
//初始化
void init_edit_flash(struct _edit_flash *edit)
{
  	edit->flag = 0;
	edit->baud = 0;
	memset(edit->buf,0,512);
}

//读取flash,获得flag和baud
//成功返回波特率,失败返回-1
int read_baud(struct _edit_flash *edit)
{
	read_flash(edit->buf);
	edit->flag = edit->buf[0];
	edit->baud = edit->buf[1] << 16;
	edit->baud += edit->buf[2];

	if (edit->flag == 0xa5)
	{
	 	return (edit->baud);
	}
	else
	{
	 	return -1;
	}
}

//写入波特率到flash
//成功返回1,失败返回0
int write_baud(struct _edit_flash *edit,int baud)
{
	edit->buf[0] = 0xa5;
	edit->buf[1] = baud >> 16;
	edit->buf[2] = baud & 0xffff;
	if (write_flash(edit->buf) > 0)
	{
		edit->flag = 0xa5;
		edit->baud = baud;

	 	return 1;
	}
	else
	{
	 	return 0;
	}
}






stm32f10x_it.c:(串口中断文件)

/**
  ******************************************************************************
  * @file    SysTick/stm32f10x_it.c 
  * @author  MCD Application Team
  * @version V3.4.0
  * @date    10/15/2010
  * @brief   Main Interrupt Service Routines.
  *          This file provides template for all exceptions handler and peripherals
  *          interrupt service routine.
  ******************************************************************************
  * @copy
  *
  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
  * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
  *
  * <h2><center>© COPYRIGHT 2010 STMicroelectronics</center></h2>
  */ 

/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_it.h"
#include "main.h"
#include "public.h"

/** @addtogroup STM32F10x_StdPeriph_Examples
  * @{
  */

/** @addtogroup SysTick
  * @{
  */

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

/******************************************************************************/
/*            Cortex-M3 Processor Exceptions Handlers                         */
/******************************************************************************/

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

/**
  * @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)
  {
  }
}

/**
  * @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 PendSV_Handler exception.
  * @param  None
  * @retval None
  */
void PendSV_Handler(void)
{
}

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

/******************************************************************************/
/*                 STM32F10x 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_stm32f10x_xx.s).                                            */
/******************************************************************************/

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

/**
  * @}
  */ 

/**
  * @}
  */ 
  	//串口1接收中断
	//与真实串口通信
	void USART1_IRQHandler(void)                             
	{
		unsigned char rx_dat;      

		if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)    			//判断发生接收中断
		{
			USART_ClearITPendingBit(USART1,    USART_IT_RXNE);        		//清除中断标志
			rx_dat = USART_ReceiveData(USART1);                      		//接收数据,整理除去前两位
			//写入fifo
			write_byte_fifo_stack(&fifo_uart1,rx_dat);
		}
	}

//返回src中dst字符串的标号,正确返回标号,失败返回-1
//src:源字符串
//dst:目标字符串
//len:源字符串比较的长度
int index_of_string(char *src,char *dst,int len)
{
	int size_dst = 0;
	int i = 0;
	int j = 0;
	
	//获得目标字符串长度
	size_dst = strlen(dst);
	//如果len小于目标字符串长度,返回失败
	if (len < size_dst)
	{
		return 0;
	}
	
	for (i = 0;i <= len - size_dst;i++)
	{
		for (j = 0;j < size_dst;j++)
		{
			if (src[i + j] != dst[j])
			{
				break;
			}
		}
		if (j == size_dst)
		{
			return i;
		}
	}
	
	return -1;
}

//串口2接收中断
//与蓝牙串口模块通信
void USART2_IRQHandler(void)                             
{
	unsigned char rx_dat;     

	if (USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)    			//判断发生接收中断
	{
		//清除中断标志
		USART_ClearITPendingBit(USART2,    USART_IT_RXNE);       
		//接收数据 		
		rx_dat = USART_ReceiveData(USART2);                      		
		//写入fifo
		write_byte_fifo_stack(&fifo_uart2,rx_dat);
	}
}
/******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/

main.c:(主文件)

/*
  	功能:蓝牙转串口模块
  	作者:jdh
	时间:2012-2-27	
*/
#include "public.h"

static __IO uint32_t TimingDelay;

//定义GPIO结构体
GPIO_InitTypeDef GPIO_InitStructure;

/* Private function prototypes -----------------------------------------------*/
void Delay(__IO uint32_t nTime);

//初始化内部晶振
static void RCC_Config(void)
{
  //将外设 RCC寄存器重设为缺省值
  RCC_DeInit();
  //内部晶振使能
  RCC_HSICmd(ENABLE);
  //使能外部晶振
  //SystemInit();
  //等待工作稳定
  while(RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET);

  if(1)
  {
    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
    FLASH_SetLatency(FLASH_Latency_2);
	//高速时钟
    RCC_HCLKConfig(RCC_SYSCLK_Div1);
    RCC_PCLK2Config(RCC_HCLK_Div1);
    RCC_PCLK1Config(RCC_HCLK_Div2);
    //设置 PLL 时钟源及倍频系数
    RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_9);
    //使能或者失能 PLL,这个参数可以取:ENABLE或者DISABLE
    RCC_PLLCmd(ENABLE);//如果PLL被用于系统时钟,那么它不能被失能
    //等待指定的 RCC 标志位设置成功 等待PLL初始化成功
    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
    //设置系统时钟(SYSCLK) 设置PLL为系统时钟源
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
    //等待PLL成功用作于系统时钟的时钟源
    //  0x00:HSI 作为系统时钟 
    //  0x04:HSE作为系统时钟 
    //  0x08:PLL作为系统时钟  
    while(RCC_GetSYSCLKSource() != 0x08);
  }
} 

//设置串口波特率
void set_uart_baud(int num,int baud)
{
	if (num == 1)
	{
		//更新串口波特率
		USART_Cmd(USART1,DISABLE);
		USART_InitStructure.USART_BaudRate = baud;
		USART_Init(USART1,&USART_InitStructure);
		USART_Cmd(USART1, ENABLE);
	}

	if (num == 2)
	{
		//更新串口波特率
		USART_Cmd(USART2,DISABLE);
		USART_InitStructure.USART_BaudRate = baud;
		USART_Init(USART2,&USART_InitStructure);
		USART_Cmd(USART2, ENABLE);
	}
}

//初始化
void init()
{
	//定义中断结构体
	NVIC_InitTypeDef NVIC_InitStructure;

	//初始化结构体
  	GPIO_StructInit(&GPIO_InitStructure);
	//初始化uart2的接收fifo
	init_fifo_stack(&fifo_uart2);
	//初始化uart1的接收fifo
	init_fifo_stack(&fifo_uart1);
	
	//中断NVIC设置:允许中断,设置优先级 
	NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn;    //更新事件 
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;   //抢占优先级0 
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;          //响应优先级1 
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;             //允许中断 
	NVIC_Init(&NVIC_InitStructure);                             //写入设置 
	
	//RCC_Config();
	//打开串口对应的外设时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 , ENABLE); 
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2 , ENABLE); 
	//初始化参数
	USART_InitStructure.USART_BaudRate = DEFAULT_BAUD;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_Parity = USART_Parity_No;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
	//初始化串口
	USART_Init(USART1,&USART_InitStructure);
	//初始化参数
	USART_InitStructure.USART_BaudRate = DEFAULT_BAUD;
	USART_Init(USART2,&USART_InitStructure);
	//TXE发送中断,TC传输完成中断,RXNE接收中断,PE奇偶错误中断,可以是多个 
	USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
	USART_ITConfig(USART2,USART_IT_RXNE,ENABLE);

	//配置UART1中断
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;				//通道设置为串口1中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; 		//中断占先等级0
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;              //中断响应优先级0
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;           		//打开中断
	NVIC_Init(&NVIC_InitStructure);                                 //初始化

	//配置UART2中断
	NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;				//通道设置为串口1中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; 		//中断占先等级0
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;              //中断响应优先级0
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;           		//打开中断
	NVIC_Init(&NVIC_InitStructure);                                 //初始化

	//启动串口
	USART_Cmd(USART1, ENABLE); 
	USART_Cmd(USART2, ENABLE); 

	//设置IO口时钟	 
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);  
	//串口1的管脚初始化  
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;                       //管脚9
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;                //选择GPIO响应速度
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;     			//复用推挽输出
    GPIO_Init(GPIOA, &GPIO_InitStructure);                          //TX初始化
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;                     	//管脚10
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;		   		//选择GPIO响应速度
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; 			//浮空输入
    GPIO_Init(GPIOA, &GPIO_InitStructure);                         	//RX初始化     
	
	//设置IO口时钟	 
	//RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);  
	//串口2的管脚初始化  
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;                       //管脚9
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;                //选择GPIO响应速度
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;     			//复用推挽输出
    GPIO_Init(GPIOA, &GPIO_InitStructure);                          //TX初始化
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;                     	//管脚10
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;		   		//选择GPIO响应速度
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; 			//浮空输入
    GPIO_Init(GPIOA, &GPIO_InitStructure);                         	//RX初始化                                              

	/* Setup SysTick Timer for 1 msec interrupts  */
	if (SysTick_Config(SystemCoreClock / 1000))
	{ 
		/* Capture error */ 
		while (1);
	}

	//设置IO口时钟	 
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE); 
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;                       //管脚9
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;                //选择GPIO响应速度
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;     			//复用推挽输出

	//初始化修改flash结构
	init_edit_flash(&edit_flash);
	//打开需要操作页面的写保护
	open_write_lock();
}

init_blue(int baud)
{
	//置高AT_EN脚
    GPIO_Init(GPIOB, &GPIO_InitStructure);                          
	GPIO_SetBits(GPIOB,GPIO_Pin_0);

	send_bt_cmd("AT+INIT");
	Delay(100);
	send_bt_cmd("AT+CMODE=1"); 
	Delay(100); 
	switch (baud)
	{
	case 4800:
		{
			send_bt_cmd("AT+UART=4800,0,0"); 
			Delay(100); 
			break;
		}
	case 9600:
		{
			send_bt_cmd("AT+UART=9600,0,0"); 
			Delay(100); 
			break;
		}
	case 19200:
		{
			send_bt_cmd("AT+UART=19200,0,0"); 
			Delay(100); 
			break;
		}
	case 38400:
		{
			send_bt_cmd("AT+UART=38400,0,0"); 
			Delay(100); 
			break;
		}
	case 57600:
		{
			send_bt_cmd("AT+UART=57600,0,0"); 
			Delay(100); 
			break;
		}
	case 115200:
		{
			send_bt_cmd("AT+UART=115200,0,0"); 
			Delay(100); 
			break;
		}
	default:
		{
			send_bt_cmd("AT+UART=9600,0,0"); 
			Delay(100); 
			break;
		}
	}
	
	//置低AT_EN脚
    GPIO_Init(GPIOB, &GPIO_InitStructure);                          
	GPIO_ResetBits(GPIOB,GPIO_Pin_0); 
}

int main(void)
{
   	struct _match_string_header match_string_header;
	struct _match_string_tail match_string_tail;
	unsigned char buffer[LEN_BUF];
	unsigned char buffer1[LEN_BUF];
	int len = 0;
	int i = 0;
	int flag = 0;
	int flag2 = 0;
	int flag3 = 0;
	int baud = 0;

	//初始化系统
	init();
	//初始化蓝牙
	//读取flash中波特率
	write_baud(&edit_flash,9600);
	baud = read_baud(&edit_flash);
	//读取有效
	if (baud > 0)
	{
	 	set_uart_baud(1,baud);
		set_uart_baud(2,baud);
	}
	else
	{
		//设置默认波特率
		set_uart_baud(1,DEFAULT_BAUD);
	  	set_uart_baud(2,DEFAULT_BAUD);
	}

	//设置默认波特率
	Delay(10);
	init_blue(DEFAULT_BAUD);
	set_uart_baud(1,DEFAULT_BAUD);
	set_uart_baud(2,DEFAULT_BAUD);
	Delay(500);
	init_blue(DEFAULT_BAUD);
	set_uart_baud(1,DEFAULT_BAUD);
	set_uart_baud(2,DEFAULT_BAUD);

	//初始化匹配字符
	init_match_string_header(&match_string_header,"AT+BAUD");
	init_match_string_tail(&match_string_tail,"END",8);

	while (1)
	{
		//读取fifo_uart1中所有数据
		len = read_all_fifo_stack(&fifo_uart1,buffer1);
		//处理
		for (i = 0;i < len;i++)
		{
		 	USART_SendData(USART2,buffer1[i]);                              //发送数据
			while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET){}	//等待发送结束
		}

		//读取fifo_uart2中所有数据
		len = read_all_fifo_stack(&fifo_uart2,buffer);
		//处理
		for (i = 0;i < len;i++)
		{
		 	if (flag == 0)
			{
				flag3 = match_string_header_state(&match_string_header,buffer[i]);
				if (flag3 == 1)
				{
					flag = 1;
				}
			}
			else
			{
				flag2 = match_string_tail_state(&match_string_tail,buffer[i]);
				if (flag2 > 0)
				{
					if (flag2 == 4800 || flag2 == 9600 || flag2 == 19200 || flag2 == 38400 || flag2 == 115200)
					{
						//重启蓝牙
						init_blue(flag2);
						//更新串口波特率
						set_uart_baud(1,flag2);
						//写入到flash
						write_baud(&edit_flash,flag2);

						//返回成功
					   	send_bt_cmd("set baud successful\n");
						flag = 0;
						continue;
					}
					else
					{
					 	send_bt_cmd("set baud fail\n");
					}
				}
			}
			
			//转发数据
			USART_SendData(USART1,buffer[i]);                              	//发送数据
			while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET){}	//等待发送结束	
		}
	}
}

/**
  * @brief  Inserts a delay time.
  * @param  nTime: specifies the delay time length, in milliseconds.
  * @retval None
  */
void Delay(__IO uint32_t nTime)
{ 
  TimingDelay = nTime;

  while(TimingDelay != 0);
}

/**
  * @brief  Decrements the TimingDelay variable.
  * @param  None
  * @retval None
  */
void TimingDelay_Decrement(void)
{
  if (TimingDelay != 0x00)
  { 
    TimingDelay--;
  }
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t* file, uint32_t line)
{ 
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

  /* Infinite loop */
  while (1)
  {
  }
}
#endif



分享到:
评论
1 楼 xyy_zero 2014-12-19  
看着听犀利的,大神,有demo吗?可以分享下不。我最近需要开发相类似的功能。

相关推荐

Global site tag (gtag.js) - Google Analytics