This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

EK-TM4C123GXL: Trouble with UART after I use QEI

Part Number: EK-TM4C123GXL

I've been working to program an RF module to control a motor which has a rotary encoder attached.

The RF module receives signals from a keyfob remote and sends a serial 10 byte output which is read as UART on the launchpad. I have it configured to evaluate the third byte (which is the unique button ID on the keyfob) in a case block to then activate the motor. The motor rotates clockwise and counter-clockwise without issue in this setup.

If I try using the QEIPositionGet() from the QEI driver library I get a reading, but following that function call my serial data from the RF module suddenly shifts. Byte 3 is now byte 9, byte 0 is now byte 6 etc.

Does anyone know why this might be happening? I've included my code for reference.

/*
 * main.c
 *
 *  Created on: Mar 14, 2021
 *      Author: dfnewell
 */

#include <stdint.h>
#include <stdbool.h>
#include <string.h>

#include "inc/tm4c123gh6pm.h"

#include "inc/hw_gpio.h"
#include "inc/hw_types.h"
#include "inc/hw_memmap.h"

#include "driverlib/debug.h"
#include "driverlib/sysctl.h"
#include "driverlib/pin_map.h"
#include "driverlib/gpio.h"
#include "driverlib/pwm.h"
#include "driverlib/timer.h"
#include "driverlib/adc.h"
#include "driverlib/uart.h"
#include "driverlib/interrupt.h"
#include "driverlib/qei.h"

#include "utils/uartstdio.h"

#define SIZE_OF_BUFFER 10

int bufferLength = 0;
int readIndex = 0;
int writeIndex = 0;



static uint32_t RFin[10];
static uint8_t RFconvert[8];

uint8_t endline = 0x0A;
void MotorRotation(uint32_t x);
uint32_t MOTOR = QEI0_BASE;
uint32_t motorHome = 0;
uint32_t UNLOAD_POS = 2388/4;
uint32_t FRONT_FACING = 2388/2;
uint32_t MOTOR_CTL_PINS = GPIO_PORTE_BASE;
uint32_t CWPIN = GPIO_PIN_1;
uint32_t CCWPIN = GPIO_PIN_2;
uint32_t MOTOR_ENABLE = GPIO_PIN_3;
int LOADSTATUS = 0;
uint32_t x = 0;
uint8_t RCVFLAG = 0;


// INITIALIZE BOARD COMPONENTS:
void InitPCUART(void)
{
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    GPIOPinConfigure(GPIO_PA0_U0RX);
    GPIOPinConfigure(GPIO_PA1_U0TX);
    GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);
		UARTStdioConfig(0,19200,16000000);
}

void InitRFModuleUART(void)
{
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_UART1);
	GPIOPinConfigure(GPIO_PB0_U1RX);
	GPIOPinConfigure(GPIO_PB1_U1TX);
	GPIOPinTypeUART(GPIO_PORTB_BASE, GPIO_PIN_0 | GPIO_PIN_1);
	UARTClockSourceSet(UART1_BASE, UART_CLOCK_PIOSC);
	UARTConfigSetExpClk(UART1_BASE, 16000000, 19200, (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));
	UARTEnable(UART1_BASE);


}

void MotorEnable(void)
{
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_QEI0);
	//Unlock GPIOD7 - Like PF0 its used for NMI - Without this step it doesn't work
	HWREG(GPIO_PORTD_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY; //In Tiva include this is the same as "_DD" in older versions (0x4C4F434B)
	HWREG(GPIO_PORTD_BASE + GPIO_O_CR) |= 0x80;
	HWREG(GPIO_PORTD_BASE + GPIO_O_LOCK) = 0;

	//Set Pins to be PHA0 and PHB0
	GPIOPinConfigure(GPIO_PD6_PHA0);
	GPIOPinConfigure(GPIO_PD7_PHB0);
	//Set GPIO pins for QEI. PhA0 -> PD6, PhB0 ->PD7. I believe this sets the pull up and makes them inputs
	GPIOPinTypeQEI(GPIO_PORTD_BASE, GPIO_PIN_6 |  GPIO_PIN_7);

	//DISable peripheral and int before configuration
	QEIDisable(QEI0_BASE);
	QEIIntDisable(QEI0_BASE,QEI_INTERROR | QEI_INTDIR | QEI_INTTIMER | QEI_INTINDEX);
	
	QEIConfigure(QEI0_BASE,QEI_CONFIG_CAPTURE_A_B|QEI_CONFIG_QUADRATURE|QEI_CONFIG_NO_RESET|QEI_CONFIG_NO_SWAP,800);
	QEIEnable(QEI0_BASE);
	QEIIntEnable(QEI0_BASE,QEI_INTINDEX);
	QEIPositionSet(QEI0_BASE,0);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
	GPIOPinTypeGPIOOutput(GPIO_PORTE_BASE,GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3);
	GPIOPinWrite(MOTOR_CTL_PINS,GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3,0x00);
}

//-----------------------------------------------------------------
// RF Recieved Parsing FOR ZPT4RD:

void char2byte(char *chars, uint8_t *ints)
{
for (int i =0; i < 8; i++){
	ints[i] = chars[i];
}
}

//------------------------------------------------------------------------------------------------------------------------------------

int main(void)
{

	SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC |   SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);

	// LEDs Enable
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
  GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE,GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3);
  GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, 0x02);
  GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 0x00);
  GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_3, 0x00);

	InitPCUART();
	InitRFModuleUART();
	MotorEnable();
	UARTprintf("Program Ready \n");
	while(1){
		GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_1, 0x02);
		GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_3, 0x00);
		GPIOPinWrite(MOTOR_CTL_PINS,MOTOR_ENABLE,0x00); // Make sure the enable pin is off to begin with.
	
		// Wait for RF transmission
		if(UARTCharsAvail(UART1_BASE)){
			GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_1, 0x00);		// Change LED colors to indicate transmission rcvd
			GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_3,GPIO_PIN_3);// and the motor is on 
			GPIOPinWrite(MOTOR_CTL_PINS,MOTOR_ENABLE,MOTOR_ENABLE); // Write the motor pin enable high
			//while((UARTCharGet(UART1_BASE) != 10)){		// Read the UART buffer and wait for the EoL flag
				RFin[writeIndex] = UARTCharGet(UART1_BASE);					// this stores the last 8 bytes before the EoL flag
				writeIndex++;
				if (writeIndex == SIZE_OF_BUFFER)
				{writeIndex = 0;
					for (int i=0;i<10;i++){
					UARTprintf("%4d",RFin[i]);}
					UARTprintf("\n");
					MotorRotation(RFin[3]);																// and process the command on the motor
				}
			//}
		}
	}
}

void MotorRotation(uint32_t x) {
  // Check received packet and assign motor actions
  // The remote only sends out signal packets in 2**n,
  // where n is the selected remote button
  switch(x) {
    // Button 1: turn CCW
    case 1: GPIOPinWrite(MOTOR_CTL_PINS,CCWPIN,CCWPIN); 
    break;
    // Button 2: turn CW
    case 2: GPIOPinWrite(MOTOR_CTL_PINS,CWPIN,CWPIN); 
    break;
    // Button 3: Home position (rear facing)
    case 4: UARTprintf("Motor position: %d",QEIPositionGet(MOTOR));
			//while(QEIPositionGet(MOTOR) > motorHome){
			//GPIOPinWrite(MOTOR_CTL_PINS,CWPIN,CWPIN);
		//}
		SysCtlDelay(10);
    break;
    // Button 4: Front Facing
    case 8: while(QEIPositionGet(MOTOR) < FRONT_FACING)
            GPIOPinWrite(MOTOR_CTL_PINS,CWPIN,CWPIN);
		SysCtlDelay(10);
    break;
    // Button 5: Load/Unload position
    case 16: if(LOADSTATUS==1){ 
              while(QEIPositionGet(MOTOR) < UNLOAD_POS){
                GPIOPinWrite(MOTOR_CTL_PINS,CCWPIN,CCWPIN);
              }
              LOADSTATUS = 0; 
              }
             else{              
              while(QEIPositionGet(MOTOR) > motorHome){
                GPIOPinWrite(MOTOR_CTL_PINS,CWPIN,CWPIN);
              }
              LOADSTATUS = 1; 
             }
						 SysCtlDelay(10);
    break;
    // Button 6: Set Home Position (Rear facing)
    case 32: QEIPositionSet(MOTOR,0);
             motorHome = QEIPositionGet(MOTOR);
							SysCtlDelay(10);
    break;

  break*/
    default: GPIOPinWrite(MOTOR_CTL_PINS,CCWPIN|CWPIN,0);
  }
  return;
}

  • Hello Darren,

    You are using QEIPositionGet quite a few times in your code and as I don't have the same module, I can't really test this. Can you narrow down with what lines of code the issue is happening? Then I may be able to offer some guidance but right now it is not very clear to me where the issue is and I'm not seeing anything notable at first look.