环境:
主机:WIN7
开发环境:MDK4.23
功能:
打开Android手机或者平台的蓝牙,通过蓝牙连接蓝牙转串口板,通过蓝牙转串口板的串口与需要调试的串口设备相连
说明:
1.PCB为我同学hunter绘制,他同时是stm32的高手,感谢他提供的支持.
2.制作了一个蓝牙转串口的板子,Android设备连接上这个板子,就相当于增加了一个串口.
3.单片机选用的是STM32F101C8,蓝牙模块选用的是HC05.HC05本身就是一个蓝牙转串口模块,再增加一个单片机的作用是可以通过单片机来配置波特率等参数.
4.蓝牙转串口板可以用MINI USB来供电,或者用3.7V锂电池来供电,板子上带有充电管理芯片,由于没锂电池,充电这块还没有测试.
5.上位机程序(Android上的串口助手)暂时没有时间写,可以在安卓市场上搜索"蓝牙串口"下一个串口助手.
实物图:
电路图:
第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