This article describes the organization of communication via Bluetooth between the microcontroller STM32 (used board STM32 Value Discovery) and any Android-powered device (smartphone, tablet, etc.). As the example shows LED control from the tablet, and sending messages back to Android from STM32 board.
As a Bluetooth module uses cheap Chinese module HC-06, which has been considered in this article.
As an Android device, I used a cheap Chinese tablet "Ainol Aurora" with an external USB-Bluetooth module (because its not have own), connected via USB Host.
Wiring diagram STM32 Discovery board to the module HC-06 is very simple:
The program for the STM32 was written in the environment CooCox CoIDE, and based on the standard example of STMicroelectronics UART communication..
Source code for STM32:
#include "stm32f10x_usart.h" #include "stm32f10x_rcc.h" #include "stm32f10x_gpio.h" #include "misc.h" int i; //ErrorStatus HSEStartUpStatus; void NVIC_Configuration(void); void GPIO_Configuration(void); void USART_Configuration(void); void USART1_IRQHandler(void); void UARTSend(const unsigned char *pucBuffer, unsigned long ulCount); int main(void) { usart_rxtx(); while(1) { } } /******************************************************************************/ /* STM32F10x Peripherals Interrupt Handlers */ /******************************************************************************/ /** * @brief This function handles USARTx global interrupt request * @param None * @retval None */ void USART1_IRQHandler(void) { if ((USART1->SR & USART_FLAG_RXNE) != (u16)RESET) { i = USART_ReceiveData(USART1); if(i == '1'){ GPIO_WriteBit(GPIOA,GPIO_Pin_8,Bit_SET); // Set '1' on PA8 UARTSend("LED ON\r\n",sizeof("LED ON\r\n")); // Send message to UART1 } else if(i == '0'){ GPIO_WriteBit(GPIOA,GPIO_Pin_8,Bit_RESET); // Set '0' on PA8 UARTSend("LED OFF\r\n",sizeof("LED OFF\r\n")); } } } void usart_rxtx(void) { const unsigned char welcome_str[] = " Welcome to Bluetooth!\r\n"; /* Enable USART1 and GPIOA clock */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE); /* NVIC Configuration */ NVIC_Configuration(); /* Configure the GPIOs */ GPIO_Configuration(); /* Configure the USART1 */ USART_Configuration(); /* Enable the USART1 Receive interrupt: this interrupt is generated when the USART1 receive data register is not empty */ USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); /* print welcome information */ UARTSend(welcome_str, sizeof(welcome_str)); } /******************************************************************************* * Function Name : GPIO_Configuration * Description : Configures the different GPIO ports *******************************************************************************/ void GPIO_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; /* Configure (PA.8) as output */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); // Save /* Configure USART1 Tx (PA.09) as alternate function push-pull */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); /* Configure USART1 Rx (PA.10) as input floating */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); } /******************************************************************************* * Function Name : USART_Configuration * Description : Configures the USART1 *******************************************************************************/ void USART_Configuration(void) { USART_InitTypeDef USART_InitStructure; /* USART1 configuration ------------------------------------------------------*/ USART_InitStructure.USART_BaudRate = 9600; // Baud Rate 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); /* Enable USART1 */ USART_Cmd(USART1, ENABLE); } /** * @brief Configures the nested vectored interrupt controller. * @param None * @retval None */ void NVIC_Configuration(void) { NVIC_InitTypeDef NVIC_InitStructure; /* Enable the USARTx Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } /******************************************************************************* * Function Name : UARTSend * Description : Send a string to the UART. * Input : - pucBuffer: buffers to be printed. * : - ulCount : buffer's length *******************************************************************************/ void UARTSend(const unsigned char *pucBuffer, unsigned long ulCount) { // // Loop while there are more characters to send. // while(ulCount--) { USART_SendData(USART1, (uint16_t) *pucBuffer++); /* Loop until the end of transmission */ while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) { } } }
Code is simple: the function GPIO_Configuration () is configured GPIO of STM32 Board, in USART_Configuration() configurable UART, and in the function NVIC_Configuration () is configuration the interrupt.
To send the string to UART uses function UARTSend(). When the data is received by an interrupt occurs and call function USART1_IRQHandler (). Depending on the assumed number 1 or 0, the command on the PA8 board ON or OFF the LED connected to it. And also, there is a transfer string "LED ON" or "LED OFF" back to UART (to Android device)
Source code for Android, I will not lead, as he is big and is based on this article, with a few additions. You can download full project in Eclipse. Also, I have attached APK file.
Video:
Download APK application for Android
Download source code and project in CooCox CooIDE for STM32 and Eclipse-project for Android
Author: Koltykov A.V.
priyal 2015-06-17 23:40:26 hey i am using stm32f303vc discovery board and hc-o6 bluetooth moduleand try to send some data to pc through bluetooth. this is my first programme with controller so i am not able to figure out what is wrong with it . can u please help me . here is my programme #include<stdio.h> #include"stm32f30x_gpio.h" #include"stm32f30x_rcc.h" #include"stm32f30x_usart.h" void USART_Printf_Example(void); int main() { volatile uint16_t a[5] = {1,2,3,4,5}; GPIO_InitTypeDef GPIO_InitStruct; RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE); GPIO_PinAFConfig(GPIOC,GPIO_PinSource5,GPIO_AF_7); GPIO_PinAFConfig(GPIOC,GPIO_PinSource4,GPIO_AF_7); GPIO_StructInit(&GPIO_InitStruct); // Initialize USART1_Tx GPIO_InitStruct.GPIO_Pin = GPIO_Pin_4; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; GPIO_Init(GPIOC, &GPIO_InitStruct); // see stm32f10x_usart.h USART_InitTypeDef USART_InitStructure; // Initialize USART structure USART_StructInit(&USART_InitStructure); USART_InitStructure.USART_BaudRate = 9600; USART_InitStructure.USART_Mode = USART_Mode_Tx; USART_Init(USART1,&USART_InitStructure); USART_Cmd(USART1, ENABLE); while(1) { USART_SendData(USART1,a[5]); } } [Reply] [Reply with quote] |
+3
|
Doan Phuong 2014-05-14 06:29:55 hi!. thanks for your share. but when i open STM project, i had error: [cc] C:\Users\ADMINI~1\AppData\Local\Temp\cc0rl9dc.s:818 : Error: registers may not be the same -- `strexh r3,r2,[r3]' [cc] C:\Users\ADMINI~1\AppData\Local\Temp\cc0rl9dc.s:772 : Error: registers may not be the same -- `strexb r3,r2,[r3]' can you help me. thanks you! [Reply] [Reply with quote] |
+19
|
matt 2014-03-28 11:38:37 Hi Admin! I have tried this code using Coocox v 1.7.6 but giving many errors. The first three errors as given below: [cc] C:\CooCox\CoIDE\workspace\abc_btooth1\main.c: In function 'USART1_IRQHandler': [cc] C:\CooCox\CoIDE\workspace\abc_btooth1\main.c:36:16: error: 'USART_TypeDef' has no member named 'SR' [cc] if ((USART1->SR & USART_FLAG_RXNE) != (u16) RESET) [cc] ^ [cc] C:\CooCox\CoIDE\workspace\abc_btooth1\main.c:36:44: error: 'u16' undeclared (first use in this function) [cc] if ((USART1->SR & USART_FLAG_RXNE) != (u16) RESET) [cc] ^ [cc] C:\CooCox\CoIDE\workspace\abc_btooth1\main.c:36:44: note: each undeclared identifier is reported only once for each function it appears in [cc] C:\CooCox\CoIDE\workspace\abc_btooth1\main.c:36:49: error: expected ')' before 'RESET' [cc] if ((USART1->SR & USART_FLAG_RXNE) != (u16) RESET) Could you please tell how to remove the errors. [Reply] [Reply with quote] |
+13
|
saw 2014-01-14 01:11:26 Hi, Can i work with a HC-O5 module? [Reply] [Reply with quote] |
+10
|
Admin 2014-01-15 18:33:41 Yes. You can work with any serial Bluetooth module [Reply] [Reply with quote] |
+20
|
Saw 2013-12-26 02:56:17 [Reply] [Reply with quote] |
+10
|
souzana 2013-12-25 02:37:44 which modifications may I do to work on STM32F4? thank you [Reply] [Reply with quote] |
+11
|
Souzana 2013-12-25 01:07:11 Hi, Is it possible to work with IAR embedded workbench instead of CooCox CooIDE? Thank you [Reply] [Reply with quote] |
+21
|
Admin 2013-12-25 12:25:06 Yes! [Reply] [Reply with quote] |
+13
|
Florin 2013-09-26 22:48:30 I did it today. I suggest that you do a boolean function readWrite() that whenever you write to outputStream you also read from the inputStream and send the readBuffer to UI with mHandler. If both read and write are ok, than return true, if one of them went wrong than return false and use resetConection before closing your ConnectedThread. See my answer here for the resetConnection. http://stackoverflow.com/questions/18420525/applica tion-using-bluetooth-spp-profile-not-working-after- update-from-android-4/19025227#19025227 But the answer about pooling is the following: In the ConnectedThread run() method do a while(true), call a method similar to readWrite(byte[] data) inside the loop, where in the first place you write something to the device, and then you read the data from the input stream. In this readWrite() method, if writing to outpustream went fine, then continue to read from the inputstream. if you got any data to the input stream, send the data to UI for processing with the mHandler (or do some processing before sending to the UI). It worked very nice for me. Unfortunately I can not write code here, but it wouldn't make much sense because my program is kind of complicated (I am using other stuff inside) but the principle is the same and it should work. [Reply] [Reply with quote] |
+11
|
Dmontufar 2013-07-23 02:20:54 Hi.I'm new in the programming of the st32 and hope that you can help me. My problem is that i compiler you program and i don't have any problem but i check the USART whith a max 232 to comunicate with my pc but this not receive nothing and i check that the GPIO A work with other program where i blink a led and thit work. You dont know why the USART dont work? thank [Reply] [Reply with quote] |
+7
|
Michael 2013-07-06 12:57:22 Hello, which external USB-Bluetooth module did you use with your Android tablet? Thanks, Michael [Reply] [Reply with quote] |
+21
|
Admin 2013-07-06 14:13:27 I don't know exact model. I used the cheapest Chinese. You can view it's photo on this page [Reply] [Reply with quote] |
+9
|
Riko 2013-04-08 07:38:13 How can I receive message from microcontroller as a polling ? thanks [Reply] [Reply with quote] |
+12
|
Florin 2013-09-26 01:39:14 Hi, Can you reply to Riko question? It is very interesting. [Reply] [Reply with quote] |
+21
|
Florin Cosmin 2013-09-25 02:17:04 I am interested in this question too. I wrote personally to you asking almost the same. In my opinion I think everything should happen in the ConnectedThread run method. Make a while true loop and write to the outputStream from there, wait a little(maybe) and then read from the inputStream. Is that right? How would you do it? I am very interesting in this. I am trying myself very hard to make it working. I have something working but I get bluetooth timeouts. I am sure it is possible to do pooling, but how? [Reply] [Reply with quote] |
+7
|