G
N
I
D
A
O
L

STM8驱动HC-05蓝牙模块

使用软件:IAR FOR STM8

编程方式:固件库

硬件配套:STM8S105C6T6实验板

1 配置蓝牙

使用 USB-TTL 模块与 HC-05 蓝牙模块连接(左为 USB 转 TTL,右为蓝牙模块):

  • 3V3-->VCC
  • TXD-->RXD
  • RXD-->TXD
  • GND-->GND

按下蓝牙模块的黑色小按钮的同时,连上电脑,这时蓝牙模块上的信号灯闪烁模式为 2s 的长闪烁,说明蓝牙进入 AT 模式,可以向它发送 AT 指令了。接着打开串口调试助手,波特率选择 38400,其他设置不用变。然后发送 AT 指令,每条指令发送成功后,调试助手会收到 OK 的信息。

部分 AT 指令如下(均以回车、换行结尾):

AT+NAME=Bluetooth-Mount256  // 蓝牙名称为Bluetooth-Mount256
AT+ROLE=0                   // 蓝牙模式为从模式
AT+CMODE=0                  // 蓝牙连接模式为任意地址连接模式
AT+PSWD="1234"              // 蓝牙配对密码为1234(注:不加双引号会返回一个 ERROR:(1D))
AT+UART=115200,0,0        // 蓝牙通信串口波特率为1152,停止位1位,无校验位(以后正常模式都会采用这个波特率来进行通讯,AT 模式依然是 38400)
AT+RMAAD                    // 清空配对列表

查询指令为:

AT+VERSION? // 获得软件版本号
AT+NAME?    // 获得设备名称
AT+PSWD?    // 获得模块密码
AT+UART?    // 获得串口参数

附上默认设置:

模块工作角色:从模式
串口参数:38400bits/s 停止位1位无校验位
配对码:1234
设备名称:HC-05
连接模式:任意蓝牙设备连接模式(恢复默认设置 AT指令:AT+ORGL)

拔下连接,再重新连接电脑,此时蓝牙模块上的信号灯闪烁模式为短闪烁,说明蓝牙模块进入正常模式,但未连接设备。要先通过手机蓝牙与搜索到蓝牙模块设备与蓝牙进行配对(在手机设置里),在蓝牙调试 app 里搜索到该设备进行连接即可,此时蓝牙模块的灯会变成间歇性闪烁(闪两下、停一会)。

第一步:
image

第二步:
image

备注:我试了这么多 app,目前只有 SPP 蓝牙串口 app 可以(这 app 广告多的一比),其他要么搜索不到要么连接超时。

接下来测试:在手机的调试助手发送字符,电脑的调试助手会收到;在电脑的调试助手发送字符,手机的调试助手会收到。

image

2 驱动代码

蓝牙驱动代码其实就是 UART 代码,如下所示:

2.1 uart.h

#ifndef __UART_H
#define __UART_H

#include "stm8s.h"
#include "stdio.h"

#ifdef _RAISONANCE_
#define PUTCHAR_PROTOTYPE int putchar (char c)
#define GETCHAR_PROTOTYPE int getchar (void)
#elif defined (_COSMIC_)
#define PUTCHAR_PROTOTYPE char putchar (char c)
#define GETCHAR_PROTOTYPE char getchar (void)
#else /* _IAR_ */
#define PUTCHAR_PROTOTYPE int putchar (int c)
#define GETCHAR_PROTOTYPE int getchar (void)
#endif /* _RAISONANCE_ */

void UART2_Config(void);
void UART2_SendByte(u8 data);
void UART2_SendStr(const unsigned char *p_str);

extern uint8_t buffer;

#endif /* __UART_H */

2.2 uart.c

重写 printf 函数,这样以后使用 printf 就可以输出信息了。

#include "UART.h"

uint8_t buffer;

void UART2_Config(void)
{
    CLK_PeripheralClockConfig(CLK_PERIPHERAL_UART2, ENABLE);
    UART2_DeInit();	
    UART2_Init((u32)115200, UART2_WORDLENGTH_8D, UART2_STOPBITS_1, UART2_PARITY_NO , UART2_SYNCMODE_CLOCK_DISABLE , UART2_MODE_TXRX_ENABLE);
    UART2_ITConfig(UART2_IT_RXNE_OR, ENABLE);
    UART2_Cmd(ENABLE);
}

void UART2_SendByte(u8 data)
{
  UART2_SendData8((unsigned char)data);
  while (UART2_GetFlagStatus(UART2_FLAG_TXE) == RESET);
}

void UART2_SendStr(const unsigned char *p_str)
{
  while(*p_str != '\0')
  {
    UART2_SendByte(*p_str);
    p_str++;
  }
}

/**********************************printf*********************************************/

/**
  * @brief Retargets the C library printf function to the UART.
  * @param c Character to send
  * @retval char Character sent
  */
PUTCHAR_PROTOTYPE
{
  /* Write a character to the UART2 */
  UART2_SendData8(c);
  /* Loop until the end of transmission */
  while (UART2_GetFlagStatus(UART2_FLAG_TXE) == RESET);
  return (c);
}

/**
  * @brief Retargets the C library scanf function to the USART.
  * @param None
  * @retval char Character to Read
  */
GETCHAR_PROTOTYPE
{
#ifdef _COSMIC_
  char c = 0;
#else
  int c = 0;
#endif
  /* Loop until the Read data register flag is SET */
  while (UART2_GetFlagStatus(UART2_FLAG_RXNE) == RESET);
  c = UART2_ReceiveData8();
  return (c);
}

2.3 stm8s_it.c

这里实现的是接收中断的功能。

#include "stm8s_it.h"
#include "uart.h"

/**
  * @brief  UART2 RX interrupt routine.
  * @param None
  * @retval
  * None
  */
 INTERRUPT_HANDLER(UART2_RX_IRQHandler, 21)
{
    /* In order to detect unexpected events during development,
       it is recommended to set a breakpoint on the following instruction.
    */
  UART2_ClearITPendingBit(UART2_IT_RXNE);
  buffer = UART2_ReceiveData8();
}
#endif /* STM8S105*/

3 简单应用:通过蓝牙控制 LED

一个很简单的测试程序:在手机上输入指令,告诉单片机需要让哪个 LED 工作,并在手机上显示哪个 LED 正在工作的信息。如果指令错误,则显示错误信息。放出主函数代码:

#include "stm8s.h"
#include "uart.h"
#include "led.h"
#include "timer.h"

void SystemInit_CLK(void);

void main(void)
{
  SystemInit_CLK();
  TIM_Init();
  LED_Init();
  UART2_Config();
  
  buffer = 0x00;
  
  __enable_interrupt();
  
  /* Infinite loop */
  while (1)
  {
    switch (buffer)
    {
    case '0':
      LED0_REVERSE;
      LED1_OFF; LED2_OFF; LED3_OFF;
      printf("LED0 WORKING!");
      break;
    case '1':
      LED1_REVERSE;
      LED0_OFF; LED2_OFF; LED3_OFF;
      printf("LED1 WORKING!");
      break;
    case '2':
      LED2_REVERSE;
      LED0_OFF; LED1_OFF; LED3_OFF;
      printf("LED2 WORKING!");
      break;
    case '3':
      LED3_REVERSE;
      LED0_OFF; LED1_OFF; LED2_OFF; 
      printf("LED3 WORKING!");
      break;
    default:
      LED0_OFF; LED1_OFF; LED2_OFF; LED3_OFF;
      printf("Wrong!");
      break;
    }
    
    TIMDelay_Nms(500);
  }
  
}

void SystemInit_CLK(void)
{
  CLK_DeInit();
  CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1); // 16MHz
  CLK_SYSCLKConfig(CLK_PRESCALER_HSIDIV1);
  CLK_HSICmd(ENABLE);
}

#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(u8* file, u32 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

蓝牙调试助手显示如下:

image

PS:不知道为什么,在单片机上发送字符串,手机上接收到的字符串是支离破碎的。

---EOF---
posted @ 2022-02-28 22:16  漫舞八月(Mount256)  阅读(342)  评论(0编辑  收藏  举报