给android设备增加串口功能
本文博客链接:http://blog.youkuaiyun.com/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