0
votes

I am trying to control some LEDs through an TM4C123GH6PM microcontroller. I wrote an Android app, that connects to the microcontroller via Bluetooth and Sends Strings to the HC-05. The HC-05 sends the commands via UART to the microcontroller. It all works, but fore some reason I need to send every Command multiple Time (most of the Time 3 times) for the microcontroller to register the command. Also, sometimes it happens that I send the command green multiple Times until the green LED turns on and then send another command but the microcontroller registers new green commands before the new command is registered. Has anyone an Idea why this is the case?

UPDATE form first Answer:

To avoid Missing Bytes from the UART I got rid of strcmp and changed my commands to just be simple Chars instead of Strings since I do not need that many different Commands and this should reduce complexity. But I still have the Same Issue. Now I sometimes have to press the Button/ send 8 times for the microcontroller to notice it. (The Commands are Unsigned Chars, ASCII: 48 == 0, 49 == 1, etc...)

#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/sysctl.h"
#include "driverlib/timer.h"
#include "driverlib/uart.h"
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include <stdbool.h>
#include <stdint.h>
#include <string.h>

// ONboarLEDS
#define redLED GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, GPIO_PIN_1)
#define blueLED GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, GPIO_PIN_2)
#define greenLED GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_3, GPIO_PIN_3)
#define LEDoff                                                                 \
  GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3, 0x00);

// External LEDS:
#define Ligth_on GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_0, GPIO_PIN_0);
#define Ligth_off GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_0, 0x00);

// Register for UART4 FIFO Data put here will be sent
#define UART4_DR_R (*((volatile uint32_t *)0x40010000))

// stores the time since system start in ms
uint32_t systemTime_ms;

bool alarm_clock = false;

// recived char form UART/Bluetooth
unsigned char rxChar;
unsigned char txChar;

// Interrupts
//////////////////////////////////////////////
void InterruptHandlerTimer0A(void) {
  // Clear the timer interrupt flag to avoid calling it up again directly
  TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
  // increase the ms counter by 1 ms
  systemTime_ms++;
}

void Uart4InterruptIsr(
    void) // this interrupt routine is to transmit data over bluetooth
{
  // clear the Interrupt FLag
  UARTIntClear(UART4_BASE, UART_INT_TX);
  // DO something?
}

// Do not call write writeStringToUart4 here to avoid missing Bytes
void Uart3InterruptIsr(
    void) // this interrupt routine is for receiving data from bluetooth
{
  // clear the Interrupt FLag
  UARTIntClear(UART3_BASE, UART_INT_RX);

  // write received Byte into an Array
  rxChar = UARTCharGet(UART3_BASE);
}

// When button is pressed
void ex_int_handler(void) {
  GPIOIntClear(GPIO_PORTF_BASE, GPIO_PIN_4);
  // Turn the Tranisistor LED off:
  GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_0, 0x00);
  // Send status
  // writeStringToUart4("\n\r");
  // writeStringToUart4("Ligth off");
  // writeStringToUart4("\n\r");
}

/////////////////////////////////////////////

// Setup
void clockSetup(void) {
  uint32_t timerPeriod;
  // configure clock
  SysCtlClockSet(SYSCTL_SYSDIV_5 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ |
                 SYSCTL_OSC_MAIN);
  // activate peripherals for the timer
  SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
  // configure timers as 32 bit timers in periodic mode
  TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC);
  // set the variable timerPeriod to the number of periods to generate a timeout
  // every ms
  timerPeriod = (SysCtlClockGet() / 1000);
  // pass the variable timerPeriod to the TIMER-0-A
  TimerLoadSet(TIMER0_BASE, TIMER_A, timerPeriod - 1);
  // register the InterruptHandlerTimer0A function as an interrupt service
  // routine
  TimerIntRegister(TIMER0_BASE, TIMER_A, &(InterruptHandlerTimer0A));
  // activate the interrupt on TIMER-0-A
  IntEnable(INT_TIMER0A);
  // generate an interrupt when TIMER-0-A generates a timeout
  TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
  // all interrupts are activated
  IntMasterEnable();
  // start the timer
  TimerEnable(TIMER0_BASE, TIMER_A);
}

void setupPeriphals(void) {
  // Peripherals for LED and GPIO
  SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
  SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);

  // button
  GPIOPinTypeGPIOInput(GPIO_PORTF_BASE, GPIO_PIN_4);
  GPIOPadConfigSet(GPIO_PORTF_BASE, GPIO_PIN_4, GPIO_STRENGTH_2MA,
                   GPIO_PIN_TYPE_STD_WPU);
  // Interrupt for button
  GPIOIntDisable(GPIO_PORTF_BASE, GPIO_PIN_4);
  GPIOIntClear(GPIO_PORTF_BASE, GPIO_PIN_4);
  GPIOIntTypeSet(GPIO_PORTF_BASE, GPIO_PIN_4, GPIO_FALLING_EDGE);
  GPIOIntRegister(GPIO_PORTF_BASE, ex_int_handler);
  GPIOIntEnable(GPIO_PORTF_BASE, GPIO_PIN_4);

  // OnboardLED (RGB)
  GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1);
  GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_2);
  GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_3);

  // Transistor Gate
  GPIOPinTypeGPIOOutput(GPIO_PORTB_BASE, GPIO_PIN_0);
  // GPIOPadConfigSet(GPIO_PORTB_BASE,GPIO_PIN_0,GPIO_STRENGTH_6MA,GPIO_PIN_TYPE_STD_WPU);
}

void setupUART(void) {
  // configure UART 4: (Sending)
  SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
  SysCtlPeripheralEnable(SYSCTL_PERIPH_UART4);
  while (!SysCtlPeripheralReady(SYSCTL_PERIPH_UART4))
    ;

  // GPIO pins for transmitting and receiving
  GPIOPinConfigure(GPIO_PC4_U4RX);
  GPIOPinConfigure(GPIO_PC5_U4TX);
  GPIOPinTypeUART(GPIO_PORTC_BASE, GPIO_PIN_4 | GPIO_PIN_5);

  // configure UART 8Bit, no parity, baudrat 38400
  UARTConfigSetExpClk(
      UART4_BASE, SysCtlClockGet(), 9600,
      (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));

  // Transmit interrupt
  IntMasterEnable();
  UARTIntRegister(UART4_BASE, &(Uart4InterruptIsr));
  UARTIntEnable(UART4_BASE, UART_INT_TX);

  // configure UART 3: (Reciving)
  SysCtlPeripheralEnable(SYSCTL_PERIPH_UART3);
  while (!SysCtlPeripheralReady(SYSCTL_PERIPH_UART3))
    ;
  GPIOPinConfigure(GPIO_PC6_U3RX);
  GPIOPinConfigure(GPIO_PC7_U3TX);
  GPIOPinTypeUART(GPIO_PORTC_BASE, GPIO_PIN_6 | GPIO_PIN_7);
  UARTConfigSetExpClk(
      UART3_BASE, SysCtlClockGet(), 9600,
      (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));

  // Receive interrupt
  UARTIntEnable(UART3_BASE, UART_INT_RX);
  UARTIntRegister(UART3_BASE, &(Uart3InterruptIsr));
}

///////////////////////////////////////////////////////

// Functions:

void writeCharToUart4(unsigned char a) {
  // puts char in FIFO, when FIFO is full waits.
  // UARTCharPut(UART4_BASE, a);
  while (!UARTSpaceAvail(UART4_BASE))
    ;
  UART4_DR_R = a;
}

void writeStringToUart4(char *str) {
  int i;
  for (i = 0; i < strlen(str); i++)
    writeCharToUart4(str[i]);
}

void delay_ms(uint32_t waitTime) {
  // Saves the current system time in ms
  uint32_t aktuell = systemTime_ms;
  // Wait until the current system time corresponds to the sum of the time at
  // the start of the delay and the waiting time
  while (aktuell + waitTime > systemTime_ms)
    ;
}

void checkCommand() {
  switch (rxChar) {
  case 49:
    LEDoff;
    redLED;
    rxChar = 48;
    break;

  case 50:
    LEDoff;
    blueLED;
    rxChar = 48;
    break;

  case 51:
    LEDoff;
    greenLED;
    rxChar = 48;
    break;

  case 52:

    LEDoff;
    rxChar = 48;
    break;

  default:
    break;
  }
}

/////////////////////////////////////////////////////////
int main(void) {
  // setup
  clockSetup();
  setupPeriphals();
  setupUART();
  writeStringToUart4("Ready");
  writeStringToUart4("\n\r");

  while (1) {
    checkCommand();

    if (alarm_clock) {
      delay_ms(10000);
      Ligth_on;
      LEDoff;
      alarm_clock = false;
    }
  }
}
1

1 Answers

0
votes

You shouldn't call writeStringToUart in an ISR function. Think about what that means: you receive a byte of data at ~9600 bits a second, you then start a transmission inside the receive function at ~9600 bits a second, so while you are transmitting in the ISR of your first received byte another byte is received but unhandled as you haven't returned from the ISR yet. Do this for the length of

LEDoff;
blueLED;
writeStringToUart4("\n\r");
writeStringToUart4("Blue LED ON");
writeStringToUart4("\n\r");

And it is quite possible that you miss a 15 bytes of incomming data because you are transmitting. Also the strcmp you do also takes quite some time.