czwartek, 6 października 2016

[19] STM32F4 - Komunikacja z modułem bluetooth HC-05

Tym razem chciałbym opisać sposób dokonania komunikacji z modułem bluetooth HC-05. Połączenie odbywa się poprzez interfejs UART, który można wykonać bezpośrednio poprzez STM32, lub z wykorzystaniem komend AT. Pierwszy sposób ma większe zastosowanie ponieważ umożliwia dołączania dodatkowych modułów z których można przesyłać dane komputer lub tablet z wykorzystaniem bezprzewodowej komunikacji.

Na początku zaprezentują podstawową wersję programu na układ STM32 po czym przejdę do komend AT.

Program dla STM32:

W zasadzie nie ma tutaj żadnych cudów. Do wykonania komunikacji pomiędzy układem a STM-em należy skonfigurować interfejs UART, przerwania do niego oraz ustawić porty TX i RX.

Poniżej funkcja ustawiająca piny dla TX oraz RX:

  1. void GPIO_INIT()
  2. {
  3.     GPIO_InitTypeDef GPIO_InitStruct;
  4.     RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
  5.     GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11; // PB10 (TX) PB11 (RX)
  6.     GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;          
  7.     GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
  8.     GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;        
  9.     GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
  10.     GPIO_Init(GPIOB, &GPIO_InitStruct);                
  11.     GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_USART3);
  12.     GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_USART3);
  13. }

Włączenie i konfiguracja UART-u:

  1. void USART_INIT(uint32_t set_baudrate)
  2. {
  3.     USART_InitTypeDef USART_InitStruct;
  4.     RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
  5.     USART_InitStruct.USART_BaudRate = set_baudrate;
  6.     USART_InitStruct.USART_WordLength = USART_WordLength_8b;
  7.     USART_InitStruct.USART_StopBits = USART_StopBits_1;
  8.     USART_InitStruct.USART_Parity = USART_Parity_No;
  9.     USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  10.     USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
  11.     USART_Init(USART3, &USART_InitStruct);
  12.     USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);
  13.     USART_Cmd(USART1, ENABLE);
  14. }

Konfiguracja przerwań NVIC:

  1. void NVIC_INIT()
  2. {
  3.     NVIC_InitTypeDef NVIC_InitStructure;
  4.     NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
  5.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  6.     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  7.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  8.     NVIC_Init(&NVIC_InitStructure);                        
  9. }

Funkcje pozwalające na komunikację:

Wysyłanie danych:

  1. int8_t USART_Buffer[8][32];
  2. uint16_t usart_buf_in[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  3. uint16_t usart_buf_out[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  4. uint16_t usart_buf_num[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  5. int __io_putchar(int c)
  6. {
  7.  send_char(c);
  8.  return c;
  9. }
  10. void USARTSend(volatile char *c)
  11. {
  12.   //Pętla działa do puki będzie jakiś znak do wysłania
  13.   while(*c)
  14.   {
  15.     while(USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET);
  16.     USART_SendData(USART3, *c++);
  17.   }
  18. }
  19. void USART_InsertToBuffer(uint8_t usart_num, uint8_t c)
  20. {
  21.  usart_num = 0;
  22.  //Sprawdza dostepne miejsce w buforze
  23.  if (usart_buf_num[usart_num] < 32)
  24.  {
  25.   if (usart_buf_in[usart_num] > (32 - 1))
  26.   {
  27.    usart_buf_in[usart_num] = 0;
  28.   }
  29.   USART_Buffer[usart_num][usart_buf_in[usart_num]] = c;
  30.   usart_buf_in[usart_num]++;
  31.   usart_buf_num[usart_num]++;
  32.  }
  33. }
  34. uint8_t USART_Getc(USART_TypeDef* USARTx)
  35. {
  36.  uint8_t usart_num = 0;
  37.  uint8_t c = 0;
  38.  //Sprawdza czy sa dane w buforze
  39.  if (usart_buf_num[usart_num] > 0)
  40.  {
  41.   if (usart_buf_out[usart_num] > (32 - 1))
  42.   {
  43.    usart_buf_out[usart_num] = 0;
  44.   }
  45.   c = USART_Buffer[usart_num][usart_buf_out[usart_num]];
  46.   USART_Buffer[usart_num][usart_buf_out[usart_num]] = 0;
  47.   usart_buf_out[usart_num]++;
  48.   usart_buf_num[usart_num]--;
  49.  }
  50.  return c;
  51. }
  52. #ifdef USART3
  53. void USART3_IRQHandler(void)
  54. {
  55.  //Sprawdzenie czy wystapilo przerwanie z powodu odebrania danych
  56.  if (USART_GetITStatus(USART3, USART_IT_RXNE))
  57.  {
  58.   #ifdef USART3_USE_CUSTOM_IRQ
  59.   //Wywołaj funckje przerwania
  60.   USART3_ReceiveHandler(USART3->DR);
  61.   #else
  62.   //Podaj dane do Buffera
  63.   USART_InsertToBuffer(0, USART3->DR);
  64.   #endif
  65.  }
  66. }
  67. #endif

Program przygotowany w taki sposób pozwoli na wysyłanie odbieranie danych przez moduł. Oczywiście przewody TX i RX należy podłączyć na krzyż. Układ zasilany jest napięciem 3.3V. Do 5V mogą być podłączone tylko odpowiednio przygotowane płytki.

HC-05 podłączony do STM-a ,z komputerem lub telefonem może się komunikować poprzez interfejs bluetooth.

Komenty AT


Teraz chciałbym przejść do opisania komend AT, jakie można wysłać do układu.


Należy pamiętać, że zgodnie z dokumentacją układu PIN34 musi być podciągnięty do zasilania. Jeżeli został podłączony do zasilania po włączeniu zasilania to parametry transmisji będą następujące:
prędkość transmisji 9600bps, 8 bitów, 1 bit stopu brak kontroli parzystości. Natomiast gdy zasilanie zostało włączone razem z podciągnięciem pinu do stanu wysokiego to parametry będą się nieco różniły: prędkość transmisji 38400, 8 bitów, 1 bit stopu oraz brak kontroli parzystości.

Aby wszystkie komendy działały należy wspomniany wcześniej pin pozostawić w stanie wysokim.

Poniżej przedstawię kilka podstawowych komend których można użyć do połączenia się z modułem. Wspomnę tylko, że te komendy w większości modułów, zwłaszcza tych starszych wersjach, akceptują tylko te wprowadzone dużymi literami. Poniżej kilka podstawowych komend:

  • AT - odpowiedź OK - sprawdzenie komunikacji
  • AT+RESET - odpowiedź OK - wyjście z trybu komend AT
  • AT+NAME - wyświetl nazwę modułu
  • AT+ADDR - wyświetli adres
  • AT+VERSION<param> - wersja oprogramowania
  • AT+UART - wyświetlenie prędkości transmisji, od 4800 do 1328400
  • AT+ROLE - tryb pracy modułu, 1 dla master, 0 dla slave
  • AT+ORGL - przywrócenie ustawień fabrycznych
  • AT+PSWD - wyświetla hasło
  • AT+CLASS - sprawdzenie typu urzadzenia
  • AT+STATE - zwraca status układu

W przypadku chęci zmiany niektórych parametrów podaje się je po "=" razem z komendą:

  • AT+NAME=PRZYKLADOWA NAZWA - zmiana nazwy
  • AT+UART=9600 - zmiana prędkości transmisji
  • AT+UART=9600,1,0,\r\n - prędkość transmisji, bit stopu, bit parzystości
  • AT+PSWD=8888 - zmiana hasła