/* This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ /* Copyright (c) 2016 King Kévin */ /* this library handles the communication with a HC-05 bluetooth module */ /* peripherals used: USART (check source for details) */ /* standard libraries */ #include // standard integer types #include // standard I/O facilities #include // general utilities #include // string utilities /* STM32 (including CM3) libraries */ #include // real-time control clock library #include // general purpose input output library #include // universal synchronous asynchronous receiver transmitter library #include // interrupt handler #include // Cortex M3 utilities #include "global.h" // common utilities #include "bluetooth_hc-05.h" // USART header and definitions /* which USART to use to talk to the bluetooth module */ #define USART USART2 #define USART_RCC RCC_USART2 #define USART_IRQ NVIC_USART2_IRQ #define USART_PORT GPIOA #define USART_PIN_TX GPIO_USART2_TX #define USART_PIN_RX GPIO_USART3_RX #define USART_BAUDRATE 9600 /* AT mode pin * to configure the HC-05 bluetooth module you need to put it in AT mode and use AT commands * there are several ways to get into AT mode, and there are several AT modes * - in full AT mode you can send all [defined] AT commands * - in mini AT mode you can't send some AT commands, such as AT+NAME * the AT mode is defined by the state of pin 34 of the module (top right) * - high: full AT mode * - low: mini AT mode * this pin is often connect to a switch on the adapter board (connected to VCC) * to enter AT mode: * - set pin 34 high when powering up, the LED will blink slowly, the baudrate will be 38400, bluetooth will be off * - set pin 34 high after powering up, the LED will keep blinking fast, the baudrate is user defined (AT+UART), bluetooth communication will keep working * setting pin 34 low after setting it high will put it into mini AT mode, except when bluetooth is not connected * when booting normally (fast blinking LED), the module will not respond to AT commands before setting pin 34 high * connect pin 34 to a STM32 GPIO to be able to go into AT mode */ #define AT_PORT GPIOB #define AT_RCC RCC_GPIOB #define AT_PIN GPIO5 /* input and output ring buffer, indexes, and available memory */ static uint8_t rx_buffer[BT_BUFFER] = {0}; static volatile uint8_t rx_i = 0; static volatile uint8_t rx_used = 0; static uint8_t tx_buffer[BT_BUFFER] = {0}; static volatile uint8_t tx_i = 0; static volatile uint8_t tx_used = 0; /* show the user how much data received over bluetooth is ready */ volatile uint8_t bt_received = 0; // same as rx_used, but since the user can write this variable we don't rely on it /* display configuration of bluetooth module */ void bt_info(void) { char* at_commands[] = {"AT+VERSION?","AT+ADDR?","AT+ROLE?","AT+UART?","AT+CMODE?","AT+STATE?","AT+NAME?"}; char* ok = "OK\r\n"; gpio_set(AT_PORT, AT_PIN); // enable AT mode for (uint8_t i=0; i=sizeof(tx_buffer)) { // idle until buffer has some space usart_enable_tx_interrupt(USART); // enable transmit interrupt __WFI(); // sleep until something happened } tx_buffer[(tx_i+tx_used)%sizeof(tx_buffer)] = c; // put character in buffer tx_used++; // update used buffer usart_enable_tx_interrupt(USART); // enable transmit interrupt } #if (USART==USART1) void usart1_isr(void) #elif (USART==USART2) void usart2_isr(void) #elif (USART==USART3) void usart3_isr(void) #endif { // USART interrupt if (usart_get_interrupt_source(USART, USART_SR_TXE)) { // data has been transmitted if (!tx_used) { // no data in the buffer to transmit usart_disable_tx_interrupt(USART); // disable transmit interrupt } else { usart_send(USART,tx_buffer[tx_i]); // put data in transmit register tx_i = (tx_i+1)%sizeof(rx_buffer); // update location on buffer tx_used--; // update used size } } if (usart_get_interrupt_source(USART, USART_SR_RXNE)) { // data has been received // only save data if there is space in the buffer if (rx_used>=sizeof(rx_buffer)) { usart_recv(USART); // read to clear interrupt } else { rx_buffer[(rx_i+rx_used)%sizeof(rx_buffer)] = usart_recv(USART); // put character in buffer rx_used++; // update used buffer bt_received = rx_used; // update available data } } }