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.

Digital ports use

Other Parts Discussed in Thread: TM4C123GH6PM

Good morning TI comunity, im a beginner and im trying to use PD2 as a digital input to check if its HIGH or LOW and make a counter to implement a speedmeter.

I would like to know if its possible and if possible some example code simple to implement. I have to detect the state where it is so that it wont count several times when im stopped at state HIGH.

Keep the good work, happy programming

  • Hello Victor,

    What you are looking for is possible. I am not sure which TM4C device you are using. On the TM4C123 PD2 is connected to a 64-bit timer. You can use the Timer in Input Capture mode and get Counter time stamp from the Wide Timer Module, which you can use to compute speed.

    Since, I do not have the input specification of your application, the above information may change.

    Regards

    Amit

  • I have a hall sensor connected to the PD2, giving me between 2.8V and 0. Already giving just HIGH or LOW.

    Im using the TM4C123H6PMI, i've already checked that afirmation of the Wide Timer module, but i can't find simple examples of it.

  • Hello Victor,

    Thanks for the clarification (details are a must). If the intent is to use the output pulse from a Hall Sensor and the convert the pulse count into speed, then I would suggest

    1. Try to move the Output of the Hall Sensor if you can to the QEI Module in TM4C123GH6PM

    2. This module is meant to compute position and speed so would be better.

    If you have can draw out the end application, that it is connected to a wheel, etc that would help build the application as well.

    Regards

    Amit

  • While Amit's advice is most always sound - I fear he's bit in violation of KISS here.

    True QEI can be massaged into this role - although I fear it adds undue complexity - and as only a single input requirement has been described - much of the QEI advantage is lost.

    Instead - feeding your hall signal to a conventional timer pin should be significantly, faster/easier.  That timer can be set up for "edge count mode" (either edge should work) and if you employ a 2nd timer as a, 'time-base" - you should be, "Off to the Races!" 

    If your timebase is set for 1 Second - and you then read & immediately clear that edge counter via the timebase's expiration (timeout) you obtain a count which linearly reflects speed.  Should 1 Second cause timer overflow you can reduce the timer period to the maximum which can be contained w/in a 32 bit timer.  (from memory - 4.29B timer ticks should exceed 1 Second)

    So - 2 timers are in play - one config'ed as edge counter - second as interval timer which regularly interrupts & then resets the edge counter - endlessly!  You must create an interrupt handler for that interval timer so that it first "reads" the edge counter and then clears it. 

    Thus - you capture the "real number of counts" per timebase interval - which provides a direct speed relationship.  (neglecting wheel-spin etc...)

  • Thank's Amit, but the solution of cb1 is better for me in 2 ways.

    First, i already made my board to connect all the sensors and i have assigned PD2 to the hall sensor, i can't change unless i cut the via and pass other wire in the board.

    Second, it looks like the implementation of timers looks quite easier. Im gonna try to investigate a little better on edge counters for Tiva to see if i can find a good example to start on.

    Thank's both to the ideas, sometimes all we need is the right keywords to look for.

  • Hello Victor

    cb1 does deserve a "verified answer" tick here.

    Cb1,

    The QEI may not add the complexity as it would be working in the DIR+CLK mode, where one pin may be tied high (to indicate the direction is the same) while the other pin can be used to provide the phase pulse.

    Regards

    Amit

  • @Amit,

    Thank you for your generous "Verify" suggestion.

    Haven't used QEI module for your parts in awhile - but do recall that the set-up/config & interrupt management - under QEI (both your MCUs and ARM others) was almost always harder/more involved - than that required for Timers.  We've hired another batch of summer interns - QEI use is "banned" till they can prove their skill/attention to detail.

    The QEI module (again yours/others) may automate or somewhat, "mask" the, "time handling" of the poster's calculation.  While that's desirable in many cases - I don't believe such shortcut trumps the benefits of clear, "count per unit time" as achieved via the dual Timer, KISS solution - past described... 

    Less automation - more user understanding - seems best/brightest for this poster.  (and others - to include cb1)

    @Victor,

    You listed 2V8 as output high signal from your hall sensor.  We work daily w/halls - that 2V8 level seems low.  Is not that sensor, "pulled up" to 3V3?  Review of the sensor's data may be in order as well as your inspection of any/all (other/unexpected) signal/component "presence" upon your hall, MCU pin...

  • Thank's or all the help so far, i've been investigating a little better the QEI module and i tried to see how it works and somehow i haven't managed to make it work and give me the velocity.

    I checked the datasheet and:

    as we can see the Velocity accumulator is given by the PhA i suppose, because im using only 1 sensor. The index is not connected to the block of interest so, i dont knwo if somehow i can make the GetVelocity from only the PhA sensor.

    I haven't found any kind of examples that ask for the velocity, only position.

    This is my code and i would liek to get the velocity. I dont know if there are still comands missing to enable some timer or counter.

    I also haven't found the list of commands i can use, i dont knwo how you guys find the comands that i can use.

    Just to remember im using a TM4C123GH6PMI

    //****************************************************************************
    
    #include <stdbool.h>
    #include <stdint.h>
    #include "inc/hw_gpio.h"
    #include "inc/hw_ints.h"
    #include "inc/hw_nvic.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "driverlib/debug.h"
    #include "driverlib/fpu.h"
    #include "driverlib/gpio.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/rom.h"
    #include "driverlib/pwm.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/systick.h"
    #include "driverlib/uart.h"
    #include "utils/uartstdio.h"
    #include "driverlib/buttons.h"
    #include "driverlib/adc.h"
    #include "driverlib/timer.h"
    #include "math.h"
    #include "driverlib/ssi.h"
    #include "driverlib/qei.h"
    
    //#define GPIO_PB6_M0PWM0         0x00011804 // j� em uso no SSI2
    //#define GPIO_PB7_M0PWM1         0x00011C04 // j� em uso no SSI2
    //#define GPIO_PB4_M0PWM2         0x00011004 // j� em uso no SSI2
    //#define GPIO_PB5_M0PWM3         0x00011404 // j� em uso no SSI2
    //#define GPIO_PE4_M0PWM4         0x00041004 // j� em uso na ADC
    //#define GPIO_PE5_M0PWM5         0x00041404 // j� em uso na ADC
    #define GPIO_PF1_M1PWM5         0x00050405
    #define GPIO_PF2_M1PWM6         0x00050805
    #define GPIO_PF3_M1PWM7         0x00050C05
    
    
    uint32_t ulADC0Value[8];
    
    bool con1, con2;
    
    unsigned long canal_0_adc0, canal_1_adc0, canal_2_adc0, canal_3_adc0, canal_5_adc0;		// ADC variables
    unsigned long ulPeriod, dutyCycle, PWMRATE = 10000, LED;								// PWM variables
    unsigned long ulResetCause;
    int y=0, yant=0, limite, estado=0, estadoant=0;
    unsigned long kp, ki, kd, KP, KI, erro, erroant, erroant2, errohist;					// Constantes dos controladores
    
    #ifdef DEBUG
    void
    __error__(char *pcFilename, uint32_t ui32Line unsigned long ulLine)
    {
    	UARTprintf("Error at line %d of %s\n", ui32Line, pcFilename);
    	while(1)
    	{
    	}
    }
    #endif
    
    void Init(void){
    
    	//Set the clock
    	ROM_SysCtlClockSet(SYSCTL_SYSDIV_2_5|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);
    
    	// Enable the peripherals used by this program.
    	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
    	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
    	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
    	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
    	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    
    	// UART Initialization
    	ROM_GPIOPinConfigure(GPIO_PA0_U0RX);
    	ROM_GPIOPinConfigure(GPIO_PA1_U0TX);
    	GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    
    	UARTStdioConfig(0, 115200, 80000000);
    
    	// Enable Timer 0 and 1
    	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
    	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1);
    
    
    	// Configure ports as I/O Digital inputs
    
    	GPIOPinTypeGPIOInput(GPIO_PORTA_BASE, GPIO_PIN_6 |GPIO_PIN_7); 	// PA6 e PA7 I/O Digital input
    	GPIOPinTypeGPIOInput(GPIO_PORTF_BASE, GPIO_PIN_4);				// Enable SW1 = GPIO_PIN_4 as I/O Digital input
    	GPIOPadConfigSet(GPIO_PORTF_BASE, GPIO_PIN_4,GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);
    
    	// Enable lazy stacking for interrupt handlers.  This allows floating-point
    	// instructions to be used within interrupt handlers
    
    	ROM_FPULazyStackingEnable();
    	ROM_FPUEnable();
    
    	// Configurar ADC_0
    
    	ADCClockConfigSet(ADC0_BASE, ADC_CLOCK_SRC_PIOSC | ADC_CLOCK_RATE_HALF, 1); //
    	ROM_ADCHardwareOversampleConfigure(ADC0_BASE, 64); // 64 samples for each value
    
    	// Enable interruption Timer 0
    	IntEnable(INT_TIMER0A);
    	ROM_TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
    	IntMasterEnable();
    	ROM_TimerEnable(TIMER0_BASE, TIMER_A);
    
    	// Enable interruption Timer 1
    
    	IntEnable(INT_TIMER1A);
    	ROM_TimerIntEnable(TIMER1_BASE, TIMER_TIMA_TIMEOUT);
    	IntMasterEnable();
    	ROM_TimerEnable(TIMER1_BASE, TIMER_A);
    }
    
    void ADCRead (void){
    
    	ROM_ADCSequenceDisable(ADC0_BASE, 0);
    
    	ROM_ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_PROCESSOR, 0);						// Maximum priority
    
    	ROM_ADCSequenceStepConfigure(ADC0_BASE, 0, 0, ADC_CTL_CH0);                    			// PE3 - canal 0
    	ROM_ADCSequenceStepConfigure(ADC0_BASE, 0, 1, ADC_CTL_CH1);                    			// PE2 - canal 1
    	ROM_ADCSequenceStepConfigure(ADC0_BASE, 0, 2, ADC_CTL_CH2);                    			// PE1 - canal 2
    	ROM_ADCSequenceStepConfigure(ADC0_BASE, 0, 3, ADC_CTL_CH3);                    			// PE0 - canal 3
    	ROM_ADCSequenceStepConfigure(ADC0_BASE, 0, 4, ADC_CTL_CH5 | ADC_CTL_IE | ADC_CTL_END);  // PD2 - canal 5
    
    	ROM_ADCSequenceEnable(ADC0_BASE, 0); //Enable Sequence0
    
    	ROM_ADCIntClear(ADC0_BASE, 0); // Clear ADC flag
    
    	ROM_ADCProcessorTrigger(ADC0_BASE, 0); //Trigger ADC in the processor
    
    	while(!ROM_ADCIntStatus(ADC0_BASE, 0, false)) {/*wait for conversion*/}
    
    	ROM_ADCSequenceDataGet(ADC0_BASE, 0, ulADC0Value); // Data to buffer
    
    	// ADC samples
    
    	canal_0_adc0 = (ulADC0Value[0]);	// Throttle
    	canal_1_adc0 = (ulADC0Value[1]); 	// Current sensor
    	canal_2_adc0 = (ulADC0Value[2]); 	// Axis X
    	canal_3_adc0 = (ulADC0Value[3]); 	// Axis Y
    	canal_5_adc0 = (ulADC0Value[4]); 	// Axis Z
    
    	con1= GPIOPinRead(GPIO_PORTA_BASE,GPIO_PIN_6);
    	con2= GPIOPinRead(GPIO_PORTA_BASE,GPIO_PIN_7);
    
    	//Write in the UART
    
    	UARTprintf("REF = %4d\r\n",canal_0_adc0);
    	UARTprintf("Contactor 1 = %4d\r\n",con1);
    	UARTprintf("Contactor 2 = %4d\r\n",con2);
    	UARTprintf("Corrente = %4d\r\n",canal_1_adc0);
    	UARTprintf("Eixo X = %4d\r\n",canal_2_adc0);
    	UARTprintf("Eixo Y =%4d\r\n",canal_3_adc0);
    	UARTprintf("Eixo Z = %4d\r\n",canal_5_adc0);
    }
    
    void Calculos (void){
    
    	//____________________________________________________________________
    
    }
    
    void InitSSI0 (void){
    
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);
    
    	HWREG(GPIO_PORTA_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY;
    	//Unlock the Port to write to commit register
    
    	HWREG(GPIO_PORTA_BASE + GPIO_O_CR) = 0xFF;
    	// Set the pins of the commit register so that AFSEL and other registers can be modified
    	//
    
    	GPIOPinConfigure(GPIO_PA2_SSI0CLK);
    	GPIOPinConfigure(GPIO_PA3_SSI0FSS);
    	GPIOPinConfigure(GPIO_PA4_SSI0RX);
    	GPIOPinConfigure(GPIO_PA5_SSI0TX);
    
    	HWREG(GPIO_PORTA_BASE + GPIO_O_LOCK) = ~(GPIO_LOCK_KEY);
    
    	// TODO: change this to select the port/pin you are using.
    	//
    	GPIOPinTypeSSI(GPIO_PORTA_BASE,GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5);
    
    	GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_3);//ACC FSS pull-up
    	GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_3,GPIO_PIN_3);
    	GPIOPinTypeGPIOOutput(GPIO_PORTE_BASE, GPIO_PIN_5);//Gyro FSS pull-up
    	GPIOPinWrite(GPIO_PORTE_BASE,GPIO_PIN_5,GPIO_PIN_5);
    
    	//
    	// Configure and enable the SSI port for SPI master mode.  Use SSI0,
    	// system clock supply, idle clock level low and active low clock in
    	// freescale SPI mode, master mode, 1MHz SSI frequency, and 8-bit data.
    	// For SPI mode, you can set the polarity of the SSI clock when the SSI
    	// unit is idle.  You can also configure what clock edge you want to
    	// capture data on.  Please reference the datasheet for more information on
    	// the different SPI modes.
    	//
    	SSIConfigSetExpClk(SSI0_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_3,
    			SSI_MODE_MASTER, 5000000, 16);
    	//
    	// Enable the SSI0 module.
    	//
    	SSIEnable(SSI0_BASE);
    }
    
    void InitSSI2 (void){
    
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI2);
    
    	HWREG(GPIO_PORTB_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY;
    	//Unlock the Port to write to commit register
    
    	HWREG(GPIO_PORTB_BASE + GPIO_O_CR) = 0xFF;
    	// Set the pins of the commit register so that AFSEL and other registers can be modified
    	//
    
    	GPIOPinConfigure(GPIO_PB4_SSI2CLK);
    	GPIOPinConfigure(GPIO_PB5_SSI2FSS);
    	GPIOPinConfigure(GPIO_PB6_SSI2RX);
    	GPIOPinConfigure(GPIO_PB7_SSI2TX);
    
    	HWREG(GPIO_PORTB_BASE + GPIO_O_LOCK) = ~(GPIO_LOCK_KEY);
    
    	// TODO: change this to select the port/pin you are using.
    	//
    	GPIOPinTypeSSI(GPIO_PORTB_BASE, GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7);
    
    	GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_3);//ACC FSS pull-up
    	GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_3,GPIO_PIN_3);
    	GPIOPinTypeGPIOOutput(GPIO_PORTE_BASE, GPIO_PIN_5);//Gyro FSS pull-up
    	GPIOPinWrite(GPIO_PORTE_BASE,GPIO_PIN_5,GPIO_PIN_5);
    
    	// Configure and enable the SSI port for SPI master mode.  Use SSI0,
    	// system clock supply, idle clock level low and active low clock in
    	// freescale SPI mode, master mode, 1MHz SSI frequency, and 8-bit data.
    	// For SPI mode, you can set the polarity of the SSI clock when the SSI
    	// unit is idle.  You can also configure what clock edge you want to
    	// capture data on.  Please reference the datasheet for more information on
    	// the different SPI modes.
    	//
    	SSIConfigSetExpClk(SSI2_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_3, SSI_MODE_MASTER, 5000000, 16);
    	//
    	// Enable the SSI2 module.
    	SSIEnable(SSI2_BASE);
    }
    void InitPWM (void) {
    	//Configure PWM Clock to match system
    	SysCtlPWMClockSet(SYSCTL_PWMDIV_1);
    
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM1);  //The Tiva Launchpad has two modules (0 and 1). Module 1 covers the LED pins
    
    	ulPeriod = SysCtlClockGet() / 10000; //PWM frequency 10kHz
    	//Configure PF1,PF2,PF3 Pins as PWM
    	GPIOPinConfigure(GPIO_PF1_M1PWM5);
    	GPIOPinConfigure(GPIO_PF2_M1PWM6);
    	GPIOPinConfigure(GPIO_PF3_M1PWM7);
    	GPIOPinTypePWM(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3);
    
    	//Configure PWM Options
    	//PWM_GEN_2 Covers M1PWM4 and M1PWM5
    	//PWM_GEN_3 Covers M1PWM6 and M1PWM7 See page 207 4/11/13 DriverLib doc
    	PWMGenConfigure(PWM1_BASE, PWM_GEN_2, PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_NO_SYNC);
    	PWMGenConfigure(PWM1_BASE, PWM_GEN_3, PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_NO_SYNC);
    
    	//Set the Period (expressed in clock ticks)
    	PWMGenPeriodSet(PWM1_BASE, PWM_GEN_2, ulPeriod);
    	PWMGenPeriodSet(PWM1_BASE, PWM_GEN_3, ulPeriod);
    	//Set PWM duty-50% (Period /2)
    	PWMPulseWidthSet(PWM1_BASE, PWM_OUT_5,ulPeriod/2);
    	PWMPulseWidthSet(PWM1_BASE, PWM_OUT_6,ulPeriod/2);
    	PWMPulseWidthSet(PWM1_BASE, PWM_OUT_7,ulPeriod/2);
    
    	// Enable the PWM generator
    	PWMGenEnable(PWM1_BASE, PWM_GEN_2);
    	PWMGenEnable(PWM1_BASE, PWM_GEN_3);
    
    	// Turn on the Output pins
    	PWMOutputState(PWM1_BASE, PWM_OUT_5_BIT |PWM_OUT_6_BIT | PWM_OUT_7_BIT, true);
    	//True or false to turn on-off the PWM port
    
    
    	// Invert PWM0 signal.
    	//
    	//PWMOutputInvert(PWM0_BASE, PWM_OUT_0_BIT, true);
    	// Switch PWM0 signal back to regular operation.
    	//
    	//PWMOutputInvert(PWM0_BASE, PWM_OUT_0_BIT, false);
    
    
    }
    
    void PWM (void){
    
    
    	if(!GPIOPinRead(GPIO_PORTF_BASE,GPIO_PIN_4)){
    
    		LED=8;
    
    		GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, LED);
    		PWMPulseWidthSet(PWM1_BASE, PWM_OUT_5,ulPeriod/2);
    		PWMPulseWidthSet(PWM1_BASE, PWM_OUT_6,ulPeriod/2);
    		// Turn on the Output pins
    		PWMOutputState(PWM1_BASE, PWM_OUT_5_BIT |PWM_OUT_6_BIT, true);
    
    	} else {
    
    		LED=2;
    
    		GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, LED);
    		PWMPulseWidthSet(PWM1_BASE, PWM_OUT_5,ulPeriod/4);
    		PWMOutputState(PWM1_BASE, PWM_OUT_5_BIT, true);
    
    		//Set PWM duty-25% (Period /4)
    		PWMPulseWidthSet(PWM1_BASE, PWM_OUT_6,ulPeriod/4);
    
    	}
    
    }
    
    void PID (void) {
    
    
    
    }
    
    void InitQEI (void) {
    
    	//short initpos = 0;
    	uint32_t MaxPos = 678;
    
    
    	//SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_QEI0);
    
    	HWREG(GPIO_PORTD_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY;
    
    	HWREG(GPIO_PORTD_BASE + GPIO_O_CR) |= 0xF0;
    	//PC4, PC5, PC6
    	HWREG(GPIO_PORTD_BASE + GPIO_O_LOCK) = 0;
    
    	GPIOPinConfigure(GPIO_PD3_IDX0);
    	GPIOPinConfigure(GPIO_PD6_PHA0);
    	GPIOPinConfigure(GPIO_PD7_PHB0);
    
    	GPIOPinTypeQEI(GPIO_PORTD_BASE, GPIO_PIN_7 |  GPIO_PIN_6 | GPIO_PIN_3);
    
    	QEIDisable(QEI0_BASE);
    	QEIIntDisable(QEI0_BASE,QEI_INTERROR | QEI_INTDIR | QEI_INTTIMER | QEI_INTINDEX);
    
    	QEIConfigure(QEI0_BASE,(QEI_CONFIG_CAPTURE_A | QEI_CONFIG_NO_RESET|QEI_CONFIG_CLOCK_DIR|QEI_CONFIG_SWAP|0x02E00), MaxPos);
    
    	//QEIPositionSet(QEI0_BASE, initpos);
    
    	//UARTprintf("\nQEI 1 Module Enable\nPosition set to %d\n\n",initpos);
    	QEIEnable(QEI0_BASE);
    
    }
    
    int main (void)
    {
    
    	Init();
    
    	InitPWM();
    
    	InitSSI0();
    
    	InitSSI2();
    
    	InitQEI();
    
    	while(1)
    
    	{
    
    
    		ADCRead();
    
    		Calculos();
    
    		PWM();
    
    		UARTprintf("Velocidade = %4d\n",QEIVelocityGet(QEI0_BASE));
    			SysCtlDelay (100);
    
    	}
    
    }
    
    
    void Timer0IntHandler(void)
    {
    	// limpa o timer
    	TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
    
    }
    
    
    void Timer1IntHandler(void)
    {
    	// limpa o timer
    	TimerIntClear(TIMER1_BASE, TIMER_TIMA_TIMEOUT);
    }
    

    One more thing to point out, if i connect my sensor to PD6, the voltage drops to 0.22V.

    I've checked PD6, is giving me 1.4V, any reason?

  • Hello Victor,

    I am more concerned on the PD6 voltage than the code. Do you mean that when the GPIO is kept in output mode and a logic 1 is written the measured voltage on the PD6 is 1.4V?

    Have you made sure that there is nothing connected to the PD6. Also can you check say PD5 and see if the voltage is fine on the other Pin?

    As mentioned by cb1, the Tack output from the sensor needs a Pull Up. Is that connected as well?

    Regards

    Amit

  • No, im saying that the PD6 is the PhA input of QEI0 and im getting 1.4V output on it, without anything connected. And form what i remember i didn't use that port for anything until now, so i suppose its not damaged.

    Also noticed that PC5 is at 3.3V, how can this be an input if its already at 3.3?

  • Hello Victor,

    Are you using the TM4C123 LaunchPad or a custom board? If custom then please share schematics (if possible). If TM4C123 launchpad then enable the Pull down and pull up sequentially to see if the voltage swings to 0 and 3.3V. That would give us some clue.

    Also as mentioned in your post (PC5 seems to be a typo, it would be PD5). if it is PD5 that you meant then please note that PD5 has USB DP and it may be in Analog Mode with Pull up Enabled.

    Regards

    Amit

  • I applied this:

    GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE, GPIO_PIN_6); 
    GPIOPinWrite(GPIO_PORTD_BASE,GPIO_PIN_6,GPIO_PIN_6);

    And the output was 2.391V. It should be 3.3V i guess

    if i put 

    GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE, GPIO_PIN_6); 
    GPIOPinWrite(GPIO_PORTD_BASE,GPIO_PIN_6,0);

    i get 1.065V

  • Hello Victor,

    Yes, when the PD6 is 1 it should be ~3.3V and when it is 0 then it should be ~0V. And since there is nothing connected to the pin, and you are not getting the full swing, I would have to infer a damaged pin.

    Regards

    Amit

  • It must be code problems, because in my other Tiva i get the same result.

    8272.QEI1.rar

    2867.QEISlave.rar

    Here the code, with QEI modules and also with SSI. One will work as slave and other as master. Still not working.

    //****************************************************************************
    
    #include <stdbool.h>
    #include <stdint.h>
    #include "inc/hw_gpio.h"
    #include "inc/hw_ints.h"
    #include "inc/hw_nvic.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "driverlib/debug.h"
    #include "driverlib/fpu.h"
    #include "driverlib/gpio.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/rom.h"
    #include "driverlib/pwm.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/systick.h"
    #include "driverlib/uart.h"
    #include "utils/uartstdio.h"
    #include "driverlib/buttons.h"
    #include "driverlib/adc.h"
    #include "driverlib/timer.h"
    #include "math.h"
    #include "driverlib/ssi.h"
    #include "driverlib/qei.h"
    
    //#define GPIO_PB6_M0PWM0         0x00011804 // j� em uso no SSI2
    //#define GPIO_PB7_M0PWM1         0x00011C04 // j� em uso no SSI2
    //#define GPIO_PB4_M0PWM2         0x00011004 // j� em uso no SSI2
    //#define GPIO_PB5_M0PWM3         0x00011404 // j� em uso no SSI2
    //#define GPIO_PE4_M0PWM4         0x00041004 // j� em uso na ADC
    //#define GPIO_PE5_M0PWM5         0x00041404 // j� em uso na ADC
    #define GPIO_PF1_M1PWM5         0x00050405
    #define GPIO_PF2_M1PWM6         0x00050805
    #define GPIO_PF3_M1PWM7         0x00050C05
    #define NUM_SSI_DATA 9
    
    uint32_t pui32DataTx[NUM_SSI_DATA];
    uint32_t pui32DataRx[NUM_SSI_DATA];
    uint32_t ulADC0Value[8];
    
    bool con1, con2;
    
    unsigned long canal_0_adc0, canal_1_adc0, canal_2_adc0, canal_3_adc0, canal_5_adc0;		// ADC variables
    unsigned long ulPeriod, dutyCycle, PWMRATE = 10000, LED;								// PWM variables
    unsigned long ulResetCause;
    int y=0, yant=0, limite, estado=0, estadoant=0;
    unsigned long kp, ki, kd, KP, KI, erro, erroant, erroant2, errohist;					// Constantes dos controladores
    
    #ifdef DEBUG
    void
    __error__(char *pcFilename, uint32_t ui32Line unsigned long ulLine)
    {
    	UARTprintf("Error at line %d of %s\n", ui32Line, pcFilename);
    	while(1)
    	{
    	}
    }
    #endif
    
    void Init(void){
    
    	//Set the clock
    	ROM_SysCtlClockSet(SYSCTL_SYSDIV_2_5|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);
    
    	// Enable the peripherals used by this program.
    	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
    	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
    	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
    	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    
    	// UART Initialization
    	ROM_GPIOPinConfigure(GPIO_PA0_U0RX);
    	ROM_GPIOPinConfigure(GPIO_PA1_U0TX);
    	GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    
    	UARTStdioConfig(0, 115200, 80000000);
    
    	// Enable Timer 0 and 1
    	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
    	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1);
    
    	// Configure ports as I/O Digital inputs
    
    	//GPIOPinTypeGPIOInput(GPIO_PORTA_BASE, GPIO_PIN_6 |GPIO_PIN_7); 	// PA6 e PA7 I/O Digital input
    	//GPIOPinTypeGPIOInput(GPIO_PORTF_BASE, GPIO_PIN_4);				// Enable SW1 = GPIO_PIN_4 as I/O Digital input
    	//GPIOPadConfigSet(GPIO_PORTF_BASE, GPIO_PIN_4,GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);
    
    	// Enable lazy stacking for interrupt handlers.  This allows floating-point
    	// instructions to be used within interrupt handlers
    
    	ROM_FPULazyStackingEnable();
    	ROM_FPUEnable();
    
    	// Configurar ADC_0
    
    	ADCClockConfigSet(ADC0_BASE, ADC_CLOCK_SRC_PIOSC | ADC_CLOCK_RATE_HALF, 1); //
    	ROM_ADCHardwareOversampleConfigure(ADC0_BASE, 64); // 64 samples for each value
    
    	// Enable interruption Timer 0
    	IntEnable(INT_TIMER0A);
    	ROM_TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
    	IntMasterEnable();
    	ROM_TimerEnable(TIMER0_BASE, TIMER_A);
    
    	// Enable interruption Timer 1
    
    	IntEnable(INT_TIMER1A);
    	ROM_TimerIntEnable(TIMER1_BASE, TIMER_TIMA_TIMEOUT);
    	IntMasterEnable();
    	ROM_TimerEnable(TIMER1_BASE, TIMER_A);
    }
    
    void InitSSI0 (void){
    
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);
    
    	HWREG(GPIO_PORTA_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY;
    	//Unlock the Port to write to commit register
    
    	HWREG(GPIO_PORTA_BASE + GPIO_O_CR) = 0xFF;
    	// Set the pins of the commit register so that AFSEL and other registers can be modified
    	//
    
    	GPIOPinConfigure(GPIO_PA2_SSI0CLK);
    	GPIOPinConfigure(GPIO_PA3_SSI0FSS);
    	GPIOPinConfigure(GPIO_PA4_SSI0RX);
    	GPIOPinConfigure(GPIO_PA5_SSI0TX);
    
    	HWREG(GPIO_PORTA_BASE + GPIO_O_LOCK) = ~(GPIO_LOCK_KEY);
    
    	// TODO: change this to select the port/pin you are using.
    	//
    	GPIOPinTypeSSI(GPIO_PORTA_BASE,GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5);
    
    	GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_3);//ACC FSS pull-up
    	GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_3,GPIO_PIN_3);
    	GPIOPinTypeGPIOOutput(GPIO_PORTE_BASE, GPIO_PIN_5);//Gyro FSS pull-up
    	GPIOPinWrite(GPIO_PORTE_BASE,GPIO_PIN_5,GPIO_PIN_5);
    
    	//
    	// Configure and enable the SSI port for SPI master mode.  Use SSI0,
    	// system clock supply, idle clock level low and active low clock in
    	// freescale SPI mode, master mode, 1MHz SSI frequency, and 8-bit data.
    	// For SPI mode, you can set the polarity of the SSI clock when the SSI
    	// unit is idle.  You can also configure what clock edge you want to
    	// capture data on.  Please reference the datasheet for more information on
    	// the different SPI modes.
    	//
    	SSIConfigSetExpClk(SSI0_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_3,
    			SSI_MODE_MASTER, 5000000, 16);
    	//
    	// Enable the SSI0 module.
    	//
    	SSIEnable(SSI0_BASE);
    }
    
    void InitSSI2 (void){
    
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI2);
    
    	HWREG(GPIO_PORTB_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY;
    	//Unlock the Port to write to commit register
    
    	HWREG(GPIO_PORTB_BASE + GPIO_O_CR) = 0xFF;
    	// Set the pins of the commit register so that AFSEL and other registers can be modified
    	//
    
    	GPIOPinConfigure(GPIO_PB4_SSI2CLK);
    	GPIOPinConfigure(GPIO_PB5_SSI2FSS);
    	GPIOPinConfigure(GPIO_PB6_SSI2RX);
    	GPIOPinConfigure(GPIO_PB7_SSI2TX);
    
    	HWREG(GPIO_PORTB_BASE + GPIO_O_LOCK) = ~(GPIO_LOCK_KEY);
    
    	// TODO: change this to select the port/pin you are using.
    	//
    	GPIOPinTypeSSI(GPIO_PORTB_BASE, GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7);
    
    	GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_3);//ACC FSS pull-up
    	GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_3,GPIO_PIN_3);
    	GPIOPinTypeGPIOOutput(GPIO_PORTE_BASE, GPIO_PIN_5);//Gyro FSS pull-up
    	GPIOPinWrite(GPIO_PORTE_BASE,GPIO_PIN_5,GPIO_PIN_5);
    
    	// Configure and enable the SSI port for SPI master mode.  Use SSI0,
    	// system clock supply, idle clock level low and active low clock in
    	// freescale SPI mode, master mode, 1MHz SSI frequency, and 8-bit data.
    	// For SPI mode, you can set the polarity of the SSI clock when the SSI
    	// unit is idle.  You can also configure what clock edge you want to
    	// capture data on.  Please reference the datasheet for more information on
    	// the different SPI modes.
    	//
    	SSIConfigSetExpClk(SSI2_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_3, SSI_MODE_MASTER, 5000000, 16);
    	//
    	// Enable the SSI2 module.
    	SSIEnable(SSI2_BASE);
    }
    
    void InitPWM (void) {
    	//Configure PWM Clock to match system
    	SysCtlPWMClockSet(SYSCTL_PWMDIV_1);
    
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM1);  //The Tiva Launchpad has two modules (0 and 1). Module 1 covers the LED pins
    
    	ulPeriod = SysCtlClockGet() / 10000; //PWM frequency 10kHz
    	//Configure PF1,PF2,PF3 Pins as PWM
    	GPIOPinConfigure(GPIO_PF1_M1PWM5);
    	GPIOPinConfigure(GPIO_PF2_M1PWM6);
    	GPIOPinConfigure(GPIO_PF3_M1PWM7);
    	GPIOPinTypePWM(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3);
    
    	//Configure PWM Options
    	//PWM_GEN_2 Covers M1PWM4 and M1PWM5
    	//PWM_GEN_3 Covers M1PWM6 and M1PWM7 See page 207 4/11/13 DriverLib doc
    	PWMGenConfigure(PWM1_BASE, PWM_GEN_2, PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_NO_SYNC);
    	PWMGenConfigure(PWM1_BASE, PWM_GEN_3, PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_NO_SYNC);
    
    	//Set the Period (expressed in clock ticks)
    	PWMGenPeriodSet(PWM1_BASE, PWM_GEN_2, ulPeriod);
    	PWMGenPeriodSet(PWM1_BASE, PWM_GEN_3, ulPeriod);
    	//Set PWM duty-50% (Period /2)
    	PWMPulseWidthSet(PWM1_BASE, PWM_OUT_5,ulPeriod/2);
    	PWMPulseWidthSet(PWM1_BASE, PWM_OUT_6,ulPeriod/2);
    	PWMPulseWidthSet(PWM1_BASE, PWM_OUT_7,ulPeriod/2);
    
    	// Enable the PWM generator
    	PWMGenEnable(PWM1_BASE, PWM_GEN_2);
    	PWMGenEnable(PWM1_BASE, PWM_GEN_3);
    
    	// Turn on the Output pins
    	PWMOutputState(PWM1_BASE, PWM_OUT_5_BIT |PWM_OUT_6_BIT | PWM_OUT_7_BIT, true);
    	//True or false to turn on-off the PWM port
    
    
    	// Invert PWM0 signal.
    	//
    	//PWMOutputInvert(PWM0_BASE, PWM_OUT_0_BIT, true);
    	// Switch PWM0 signal back to regular operation.
    	//
    	//PWMOutputInvert(PWM0_BASE, PWM_OUT_0_BIT, false);
    
    
    }
    
    void PWM (void){
    
    
    	if(!GPIOPinRead(GPIO_PORTF_BASE,GPIO_PIN_4)){
    
    		LED=8;
    
    		GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, LED);
    		PWMPulseWidthSet(PWM1_BASE, PWM_OUT_5,ulPeriod/2);
    		PWMPulseWidthSet(PWM1_BASE, PWM_OUT_6,ulPeriod/2);
    		// Turn on the Output pins
    		PWMOutputState(PWM1_BASE, PWM_OUT_5_BIT |PWM_OUT_6_BIT, true);
    
    	} else {
    
    		LED=2;
    
    		GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, LED);
    		PWMPulseWidthSet(PWM1_BASE, PWM_OUT_5,ulPeriod/4);
    		PWMOutputState(PWM1_BASE, PWM_OUT_5_BIT, true);
    
    		//Set PWM duty-25% (Period /4)
    		PWMPulseWidthSet(PWM1_BASE, PWM_OUT_6,ulPeriod/4);
    
    	}
    
    }
    
    void InitComunication (void) {
    
    	uint32_t ui32Index;
    
    	while(SSIDataGetNonBlocking(SSI2_BASE, &pui32DataRx[0]));
    
    	//
    	// Initialize the data to send.
    	//
    	pui32DataTx[0] = (0xFF);
    	pui32DataTx[1] = (4093);
    	pui32DataTx[2] = (2040);
    	pui32DataTx[3] = (1024);//read control reg1
    	pui32DataTx[4] = (512);//read status reg
    	pui32DataTx[5] = (256);//read status reg
    	pui32DataTx[6] = (128);//read status reg
    	pui32DataTx[7] = (64);//read status reg
    	pui32DataTx[8] = (0x000);//read status reg
    
    	//
    	// Display indication that the SSI is transmitting data.
    	//
    	//UARTprintf("Sent:\n  ");
    
    	//
    	// Send 3 bytes of data.
    	//
    	for(ui32Index = 0; ui32Index < NUM_SSI_DATA; ui32Index++)
    	{
    		//
    		// Display the data that SSI is transferring.
    		//
    		UARTprintf("%02x ", pui32DataTx[ui32Index]);
    
    		//
    		// Send the data using the "blocking" put function.  This function
    		// will wait until there is room in the send FIFO before returning.
    		// This allows you to assure that all the data you send makes it into
    		// the send FIFO.
    		//
    		GPIOPinWrite(GPIO_PORTE_BASE,GPIO_PIN_5,0);
    		SSIDataPut(SSI2_BASE, pui32DataTx[ui32Index]);
    
    		SysCtlDelay(40);
    		GPIOPinWrite(GPIO_PORTE_BASE,GPIO_PIN_5,GPIO_PIN_5);
    	}
    
    	//
    	// Wait until SSI0 is done transferring all the data in the transmit FIFO.
    	//
    	while(SSIBusy(SSI2_BASE))
    	{
    	}
    
    	//
    	// Display indication that the SSI is receiving data.
    	//
    	UARTprintf("\nReceived:\n  ");
    
    	//
    	// Receive 3 bytes of data.
    	//
    	for(ui32Index = 0; ui32Index < NUM_SSI_DATA; ui32Index++)
    	{
    		//
    		// Receive the data using the "blocking" Get function. This function
    		// will wait until there is data in the receive FIFO before returning.
    		//
    		SSIDataGet(SSI2_BASE, &pui32DataRx[ui32Index]);
    
    		//
    		// 8-bit data, mask off the MSB.
    		//
    		pui32DataRx[ui32Index] &= 0xFFF;
    
    		//
    		// Display the data that SSI1 received.
    		//
    		UARTprintf("%02x ", pui32DataRx[ui32Index]);
    	}
    
    	UARTprintf("\n\n");
    }
    
    void InitQEI0 (void) {
    
    	//short initpos = 0;
    	uint32_t MaxPos = 678;
    
    
    	//SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_QEI0);
    
    	HWREG(GPIO_PORTD_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY;
    
    	HWREG(GPIO_PORTD_BASE + GPIO_O_CR) |= 0xF0;
    	//PD3, PD6, PD7
    	HWREG(GPIO_PORTD_BASE + GPIO_O_LOCK) = 0;
    
    	GPIOPinConfigure(GPIO_PD3_IDX0);
    	GPIOPinConfigure(GPIO_PD6_PHA0);
    	GPIOPinConfigure(GPIO_PD7_PHB0);
    
    	GPIOPinTypeQEI(GPIO_PORTD_BASE, GPIO_PIN_7 |  GPIO_PIN_6 | GPIO_PIN_3);
    
    	QEIDisable(QEI0_BASE);
    	QEIIntDisable(QEI0_BASE,QEI_INTERROR | QEI_INTDIR | QEI_INTTIMER | QEI_INTINDEX);
    
    	QEIConfigure(QEI0_BASE,(QEI_CONFIG_CAPTURE_A | QEI_CONFIG_NO_RESET|QEI_CONFIG_CLOCK_DIR|QEI_CONFIG_SWAP|0x02E00), MaxPos);
    
    	//QEIPositionSet(QEI0_BASE, initpos);
    
    	//UARTprintf("\nQEI 1 Module Enable\nPosition set to %d\n\n",initpos);
    	QEIEnable(QEI0_BASE);
    
    }
    
    void InitQEI1 (void) {
    
    	short initpos = 0;
    	uint32_t MaxPos = 678;
    
    
    	//SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_QEI1);
    
    	HWREG(GPIO_PORTC_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY;
    
    	HWREG(GPIO_PORTC_BASE + GPIO_O_CR) |= 0xF0;
    	//PC4, PC5, PC6
    	HWREG(GPIO_PORTC_BASE + GPIO_O_LOCK) = 0;
    
    	GPIOPinConfigure(GPIO_PC4_IDX1);
    	GPIOPinConfigure(GPIO_PC5_PHA1);
    	GPIOPinConfigure(GPIO_PC6_PHB1);
    
    	GPIOPinTypeQEI(GPIO_PORTC_BASE, GPIO_PIN_6 |  GPIO_PIN_5|  GPIO_PIN_4);
    
    	QEIDisable(QEI1_BASE);
    	QEIIntDisable(QEI1_BASE,QEI_INTERROR | QEI_INTDIR | QEI_INTTIMER | QEI_INTINDEX);
    
    	QEIConfigure(QEI1_BASE
    			,(QEI_CONFIG_CAPTURE_A_B | QEI_CONFIG_NO_RESET|QEI_CONFIG_CLOCK_DIR|QEI_CONFIG_SWAP|0x02E00)
    			,MaxPos);
    
    	QEIPositionSet(QEI1_BASE, initpos);
    
    	UARTprintf("\nQEI 1 Module Enable\nPosition set to %d\n\n",initpos);
    
    	QEIEnable(QEI1_BASE);
    
    }
    
    int main (void)
    {
    
    	Init();
    
    	InitPWM();
    
    	InitSSI0();
    
    	InitSSI2();
    
    	InitComunication();
    
    	while(1)
    
    	{
    
    
    		PWM();
    
    		InitSSI0();
    
    		InitSSI2();
    
    		InitComunication();
    
    	}
    
    }
    
    
    void Timer0IntHandler(void)
    {
    	// limpa o timer
    	TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
    
    }
    
    
    void Timer1IntHandler(void)
    {
    	// limpa o timer
    	TimerIntClear(TIMER1_BASE, TIMER_TIMA_TIMEOUT);
    }
    

    //****************************************************************************
    
    #include <stdbool.h>
    #include <stdint.h>
    #include "inc/hw_gpio.h"
    #include "inc/hw_ints.h"
    #include "inc/hw_nvic.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "driverlib/debug.h"
    #include "driverlib/fpu.h"
    #include "driverlib/gpio.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/rom.h"
    #include "driverlib/pwm.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/systick.h"
    #include "driverlib/uart.h"
    #include "utils/uartstdio.h"
    #include "driverlib/buttons.h"
    #include "driverlib/adc.h"
    #include "driverlib/timer.h"
    #include "math.h"
    #include "driverlib/ssi.h"
    #include "driverlib/qei.h"
    
    //#define GPIO_PB6_M0PWM0         0x00011804 // j� em uso no SSI2
    //#define GPIO_PB7_M0PWM1         0x00011C04 // j� em uso no SSI2
    //#define GPIO_PB4_M0PWM2         0x00011004 // j� em uso no SSI2
    //#define GPIO_PB5_M0PWM3         0x00011404 // j� em uso no SSI2
    //#define GPIO_PE4_M0PWM4         0x00041004 // j� em uso na ADC
    //#define GPIO_PE5_M0PWM5         0x00041404 // j� em uso na ADC
    #define GPIO_PF1_M1PWM5         0x00050405
    #define GPIO_PF2_M1PWM6         0x00050805
    #define GPIO_PF3_M1PWM7         0x00050C05
    #define NUM_SSI_DATA 9
    
    uint32_t pui32DataTx[NUM_SSI_DATA];
    uint32_t pui32DataRx[NUM_SSI_DATA];
    uint32_t ulADC0Value[8];
    
    bool con1, con2;
    
    unsigned long canal_0_adc0, canal_1_adc0, canal_2_adc0, canal_3_adc0, canal_5_adc0;		// ADC variables
    unsigned long ulPeriod, dutyCycle, PWMRATE = 10000, LED;								// PWM variables
    unsigned long ulResetCause;
    int y=0, yant=0, limite, estado=0, estadoant=0;
    unsigned long kp, ki, kd, KP, KI, erro, erroant, erroant2, errohist;					// Constantes dos controladores
    
    #ifdef DEBUG
    void
    __error__(char *pcFilename, uint32_t ui32Line unsigned long ulLine)
    {
    	UARTprintf("Error at line %d of %s\n", ui32Line, pcFilename);
    	while(1)
    	{
    	}
    }
    #endif
    
    void Init(void){
    
    	//Set the clock
    	ROM_SysCtlClockSet(SYSCTL_SYSDIV_2_5|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);
    
    	// Enable the peripherals used by this program.
    	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
    	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
    	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
    	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
    	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    
    	// UART Initialization
    	ROM_GPIOPinConfigure(GPIO_PA0_U0RX);
    	ROM_GPIOPinConfigure(GPIO_PA1_U0TX);
    	GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    
    	UARTStdioConfig(0, 115200, 80000000);
    
    	// Enable Timer 0 and 1
    	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
    	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1);
    
    
    	// Configure ports as I/O Digital inputs
    
    	GPIOPinTypeGPIOInput(GPIO_PORTA_BASE, GPIO_PIN_6 |GPIO_PIN_7); 	// PA6 e PA7 I/O Digital input
    	GPIOPinTypeGPIOInput(GPIO_PORTF_BASE, GPIO_PIN_4);				// Enable SW1 = GPIO_PIN_4 as I/O Digital input
    	GPIOPadConfigSet(GPIO_PORTF_BASE, GPIO_PIN_4,GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);
    
    	//GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE, GPIO_PIN_6);				// Enable SW1 = GPIO_PIN_4 as I/O Digital input
    	//GPIOPadConfigSet(GPIO_PORTD_BASE, GPIO_PIN_6,GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);
    
    	// Enable lazy stacking for interrupt handlers.  This allows floating-point
    	// instructions to be used within interrupt handlers
    
    	ROM_FPULazyStackingEnable();
    	ROM_FPUEnable();
    
    	// Configurar ADC_0
    
    	ADCClockConfigSet(ADC0_BASE, ADC_CLOCK_SRC_PIOSC | ADC_CLOCK_RATE_HALF, 1); //
    	ROM_ADCHardwareOversampleConfigure(ADC0_BASE, 64); // 64 samples for each value
    
    	// Enable interruption Timer 0
    	IntEnable(INT_TIMER0A);
    	ROM_TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
    	IntMasterEnable();
    	ROM_TimerEnable(TIMER0_BASE, TIMER_A);
    
    	// Enable interruption Timer 1
    
    	IntEnable(INT_TIMER1A);
    	ROM_TimerIntEnable(TIMER1_BASE, TIMER_TIMA_TIMEOUT);
    	IntMasterEnable();
    	ROM_TimerEnable(TIMER1_BASE, TIMER_A);
    }
    
    void ADCRead (void){
    
    	ROM_ADCSequenceDisable(ADC0_BASE, 0);
    
    	ROM_ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_PROCESSOR, 0);						// Maximum priority
    
    	ROM_ADCSequenceStepConfigure(ADC0_BASE, 0, 0, ADC_CTL_CH0);                    			// PE3 - canal 0
    	ROM_ADCSequenceStepConfigure(ADC0_BASE, 0, 1, ADC_CTL_CH1);                    			// PE2 - canal 1
    	ROM_ADCSequenceStepConfigure(ADC0_BASE, 0, 2, ADC_CTL_CH2);                    			// PE1 - canal 2
    	ROM_ADCSequenceStepConfigure(ADC0_BASE, 0, 3, ADC_CTL_CH3);                    			// PE0 - canal 3
    	ROM_ADCSequenceStepConfigure(ADC0_BASE, 0, 4, ADC_CTL_CH5 | ADC_CTL_IE | ADC_CTL_END);  // PD2 - canal 5
    
    	ROM_ADCSequenceEnable(ADC0_BASE, 0); //Enable Sequence0
    
    	ROM_ADCIntClear(ADC0_BASE, 0); // Clear ADC flag
    
    	ROM_ADCProcessorTrigger(ADC0_BASE, 0); //Trigger ADC in the processor
    
    	while(!ROM_ADCIntStatus(ADC0_BASE, 0, false)) {/*wait for conversion*/}
    
    	ROM_ADCSequenceDataGet(ADC0_BASE, 0, ulADC0Value); // Data to buffer
    
    	// ADC samples
    
    	canal_0_adc0 = (ulADC0Value[0]);	// Throttle
    	canal_1_adc0 = (ulADC0Value[1]); 	// Current sensor
    	canal_2_adc0 = (ulADC0Value[2]); 	// Axis X
    	canal_3_adc0 = (ulADC0Value[3]); 	// Axis Y
    	canal_5_adc0 = (ulADC0Value[4]); 	// Axis Z
    
    	con1= GPIOPinRead(GPIO_PORTA_BASE,GPIO_PIN_6);
    	con2= GPIOPinRead(GPIO_PORTA_BASE,GPIO_PIN_7);
    
    	//Write in the UART
    
    	/*UARTprintf("REF = %4d\r\n",canal_0_adc0);
    	UARTprintf("Contactor 1 = %6d\r\n",con1);
    	UARTprintf("Contactor 2 = %6d\r\n",con2);
    	UARTprintf("Corrente = %4d\r\n",canal_1_adc0);
    	UARTprintf("Eixo X = %4d\r\n",canal_2_adc0);
    	UARTprintf("Eixo Y =%4d\r\n",canal_3_adc0);
    	UARTprintf("Eixo Z = %4d\r\n",canal_5_adc0);*/
    }
    
    void Calculos (void){
    
    	//____________________________________________________________________
    
    }
    
    void InitSSI0 (void){
    
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);
    
    	HWREG(GPIO_PORTA_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY;
    	//Unlock the Port to write to commit register
    
    	HWREG(GPIO_PORTA_BASE + GPIO_O_CR) = 0xFF;
    	// Set the pins of the commit register so that AFSEL and other registers can be modified
    	//
    
    	GPIOPinConfigure(GPIO_PA2_SSI0CLK);
    	GPIOPinConfigure(GPIO_PA3_SSI0FSS);
    	GPIOPinConfigure(GPIO_PA4_SSI0RX);
    	GPIOPinConfigure(GPIO_PA5_SSI0TX);
    
    	HWREG(GPIO_PORTA_BASE + GPIO_O_LOCK) = ~(GPIO_LOCK_KEY);
    
    	// TODO: change this to select the port/pin you are using.
    	//
    	GPIOPinTypeSSI(GPIO_PORTA_BASE,GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5);
    
    	GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_3);//ACC FSS pull-up
    	GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_3,GPIO_PIN_3);
    	GPIOPinTypeGPIOOutput(GPIO_PORTE_BASE, GPIO_PIN_5);//Gyro FSS pull-up
    	GPIOPinWrite(GPIO_PORTE_BASE,GPIO_PIN_5,GPIO_PIN_5);
    
    	//
    	// Configure and enable the SSI port for SPI master mode.  Use SSI0,
    	// system clock supply, idle clock level low and active low clock in
    	// freescale SPI mode, master mode, 1MHz SSI frequency, and 8-bit data.
    	// For SPI mode, you can set the polarity of the SSI clock when the SSI
    	// unit is idle.  You can also configure what clock edge you want to
    	// capture data on.  Please reference the datasheet for more information on
    	// the different SPI modes.
    	//
    	SSIConfigSetExpClk(SSI0_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_3,
    			SSI_MODE_SLAVE, 5000000, 16);
    	//
    	// Enable the SSI0 module.
    	//
    	SSIEnable(SSI0_BASE);
    }
    
    void InitSSI2 (void){
    
    
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI2);
    
    	HWREG(GPIO_PORTB_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY;
    	//Unlock the Port to write to commit register
    
    	HWREG(GPIO_PORTB_BASE + GPIO_O_CR) = 0xFF;
    	// Set the pins of the commit register so that AFSEL and other registers can be modified
    	//
    
    	GPIOPinConfigure(GPIO_PB4_SSI2CLK);
    	GPIOPinConfigure(GPIO_PB5_SSI2FSS);
    	GPIOPinConfigure(GPIO_PB6_SSI2RX);
    	GPIOPinConfigure(GPIO_PB7_SSI2TX);
    
    	HWREG(GPIO_PORTB_BASE + GPIO_O_LOCK) = ~(GPIO_LOCK_KEY);
    
    	// TODO: change this to select the port/pin you are using.
    	//
    	GPIOPinTypeSSI(GPIO_PORTB_BASE, GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7);
    
    	GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_3);//ACC FSS pull-up
    	GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_3,GPIO_PIN_3);
    	GPIOPinTypeGPIOOutput(GPIO_PORTE_BASE, GPIO_PIN_5);//Gyro FSS pull-up
    	GPIOPinWrite(GPIO_PORTE_BASE,GPIO_PIN_5,GPIO_PIN_5);
    
    	// Configure and enable the SSI port for SPI master mode.  Use SSI0,
    	// system clock supply, idle clock level low and active low clock in
    	// freescale SPI mode, master mode, 1MHz SSI frequency, and 8-bit data.
    	// For SPI mode, you can set the polarity of the SSI clock when the SSI
    	// unit is idle.  You can also configure what clock edge you want to
    	// capture data on.  Please reference the datasheet for more information on
    	// the different SPI modes.
    	//
    	SSIConfigSetExpClk(SSI2_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_3, SSI_MODE_SLAVE, 5000000, 16);
    	//
    	// Enable the SSI2 module.
    	SSIEnable(SSI2_BASE);
    }
    
    
    void InitComunication (void) {
    
    	uint32_t ui32Index;
    
    	while(SSIDataGetNonBlocking(SSI2_BASE, &pui32DataRx[0]));
    
    	//
    	// Initialize the data to send.
    	//
    	pui32DataTx[0] = (0xFF);
    	pui32DataTx[1] = (canal_0_adc0);
    	pui32DataTx[2] = (con1);
    	pui32DataTx[3] = (con2);//read control reg1
    	pui32DataTx[4] = (canal_1_adc0);//read status reg
    	pui32DataTx[5] = (canal_2_adc0);//read status reg
    	pui32DataTx[6] = (canal_3_adc0);//read status reg
    	pui32DataTx[7] = (canal_5_adc0);//read status reg
    	pui32DataTx[8] = (0x000);//read status reg
    
    	//
    	// Display indication that the SSI is transmitting data.
    	//
    	//UARTprintf("Sent:\n  ");
    
    	//
    	// Send 3 bytes of data.
    	//
    	for(ui32Index = 0; ui32Index < NUM_SSI_DATA; ui32Index++)
    	{
    		//
    		// Display the data that SSI is transferring.
    		//
    		UARTprintf("%02x ", pui32DataTx[ui32Index]);
    
    		//
    		// Send the data using the "blocking" put function.  This function
    		// will wait until there is room in the send FIFO before returning.
    		// This allows you to assure that all the data you send makes it into
    		// the send FIFO.
    		//
    		GPIOPinWrite(GPIO_PORTE_BASE,GPIO_PIN_5,0);
    		SSIDataPut(SSI2_BASE, pui32DataTx[ui32Index]);
    
    		SysCtlDelay(40);
    		GPIOPinWrite(GPIO_PORTE_BASE,GPIO_PIN_5,GPIO_PIN_5);
    	}
    	UARTprintf("\n");
    	//
    	// Wait until SSI0 is done transferring all the data in the transmit FIFO.
    	//
    	while(SSIBusy(SSI2_BASE))
    	{
    	}
    
    	//
    	// Display indication that the SSI is receiving data.
    	//
    	UARTprintf("\nReceived:\n  ");
    
    	//
    	// Receive 3 bytes of data.
    	//
    	for(ui32Index = 0; ui32Index < NUM_SSI_DATA; ui32Index++)
    	{
    		//
    		// Receive the data using the "blocking" Get function. This function
    		// will wait until there is data in the receive FIFO before returning.
    		//
    		SSIDataGet(SSI2_BASE, &pui32DataRx[ui32Index]);
    
    		//
    		// 8-bit data, mask off the MSB.
    		//
    		pui32DataRx[ui32Index] &= 0xFFF;
    
    		//
    		// Display the data that SSI1 received.
    		//
    		UARTprintf("%03x ", pui32DataRx[ui32Index]);
    	}
    
    	UARTprintf("\n\n");
    }
    
    
    void InitPWM (void) {
    	//Configure PWM Clock to match system
    	SysCtlPWMClockSet(SYSCTL_PWMDIV_1);
    
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM1);  //The Tiva Launchpad has two modules (0 and 1). Module 1 covers the LED pins
    
    	ulPeriod = SysCtlClockGet() / 10000; //PWM frequency 10kHz
    	//Configure PF1,PF2,PF3 Pins as PWM
    	GPIOPinConfigure(GPIO_PF1_M1PWM5);
    	GPIOPinConfigure(GPIO_PF2_M1PWM6);
    	GPIOPinConfigure(GPIO_PF3_M1PWM7);
    	GPIOPinTypePWM(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3);
    
    	//Configure PWM Options
    	//PWM_GEN_2 Covers M1PWM4 and M1PWM5
    	//PWM_GEN_3 Covers M1PWM6 and M1PWM7 See page 207 4/11/13 DriverLib doc
    	PWMGenConfigure(PWM1_BASE, PWM_GEN_2, PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_NO_SYNC);
    	PWMGenConfigure(PWM1_BASE, PWM_GEN_3, PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_NO_SYNC);
    
    	//Set the Period (expressed in clock ticks)
    	PWMGenPeriodSet(PWM1_BASE, PWM_GEN_2, ulPeriod);
    	PWMGenPeriodSet(PWM1_BASE, PWM_GEN_3, ulPeriod);
    	//Set PWM duty-50% (Period /2)
    	PWMPulseWidthSet(PWM1_BASE, PWM_OUT_5,ulPeriod/2);
    	PWMPulseWidthSet(PWM1_BASE, PWM_OUT_6,ulPeriod/2);
    	PWMPulseWidthSet(PWM1_BASE, PWM_OUT_7,ulPeriod/2);
    
    	// Enable the PWM generator
    	PWMGenEnable(PWM1_BASE, PWM_GEN_2);
    	PWMGenEnable(PWM1_BASE, PWM_GEN_3);
    
    	// Turn on the Output pins
    	PWMOutputState(PWM1_BASE, PWM_OUT_5_BIT |PWM_OUT_6_BIT | PWM_OUT_7_BIT, true);
    	//True or false to turn on-off the PWM port
    
    
    	// Invert PWM0 signal.
    	//
    	//PWMOutputInvert(PWM0_BASE, PWM_OUT_0_BIT, true);
    	// Switch PWM0 signal back to regular operation.
    	//
    	//PWMOutputInvert(PWM0_BASE, PWM_OUT_0_BIT, false);
    
    
    }
    
    void PWM (void){
    
    
    	if(!GPIOPinRead(GPIO_PORTF_BASE,GPIO_PIN_4)){
    
    		LED=8;
    
    		GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, LED);
    		PWMPulseWidthSet(PWM1_BASE, PWM_OUT_5,ulPeriod/2);
    		PWMPulseWidthSet(PWM1_BASE, PWM_OUT_6,ulPeriod/2);
    		// Turn on the Output pins
    		PWMOutputState(PWM1_BASE, PWM_OUT_5_BIT |PWM_OUT_6_BIT, true);
    
    	} else {
    
    		LED=2;
    
    		GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, LED);
    		PWMPulseWidthSet(PWM1_BASE, PWM_OUT_5,ulPeriod/4);
    		PWMOutputState(PWM1_BASE, PWM_OUT_5_BIT, true);
    
    		//Set PWM duty-25% (Period /4)
    		PWMPulseWidthSet(PWM1_BASE, PWM_OUT_6,ulPeriod/4);
    
    	}
    
    }
    
    void PID (void) {
    
    
    
    }
    
    void InitQEI0 (void) {
    
    	//short initpos = 0;
    	uint32_t MaxPos = 678;
    
    
    	//SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_QEI0);
    
    	HWREG(GPIO_PORTD_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY;
    
    	HWREG(GPIO_PORTD_BASE + GPIO_O_CR) |= 0xF0;
    	//PD3, PD6, PD7
    	HWREG(GPIO_PORTD_BASE + GPIO_O_LOCK) = 0;
    
    	GPIOPinConfigure(GPIO_PD3_IDX0);
    	GPIOPinConfigure(GPIO_PD6_PHA0);
    	GPIOPinConfigure(GPIO_PD7_PHB0);
    
    	GPIOPinTypeQEI(GPIO_PORTD_BASE, GPIO_PIN_7 |  GPIO_PIN_6 | GPIO_PIN_3);
    
    	QEIDisable(QEI0_BASE);
    	QEIIntDisable(QEI0_BASE,QEI_INTERROR | QEI_INTDIR | QEI_INTTIMER | QEI_INTINDEX);
    
    	QEIConfigure(QEI0_BASE,(QEI_CONFIG_CAPTURE_A | QEI_CONFIG_NO_RESET|QEI_CONFIG_CLOCK_DIR|QEI_CONFIG_SWAP|0x02E00), MaxPos);
    
    	//QEIPositionSet(QEI0_BASE, initpos);
    
    	//UARTprintf("\nQEI 1 Module Enable\nPosition set to %d\n\n",initpos);
    	QEIEnable(QEI0_BASE);
    
    }
    
    void InitQEI1 (void) {
    
    	short initpos = 0;
    	uint32_t MaxPos = 678;
    
    
    	//SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_QEI1);
    
    	HWREG(GPIO_PORTC_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY;
    
    	HWREG(GPIO_PORTC_BASE + GPIO_O_CR) |= 0xF0;
    	//PC4, PC5, PC6
    	HWREG(GPIO_PORTC_BASE + GPIO_O_LOCK) = 0;
    
    	GPIOPinConfigure(GPIO_PC4_IDX1);
    	GPIOPinConfigure(GPIO_PC5_PHA1);
    	GPIOPinConfigure(GPIO_PC6_PHB1);
    
    	GPIOPinTypeQEI(GPIO_PORTC_BASE, GPIO_PIN_6 |  GPIO_PIN_5|  GPIO_PIN_4);
    
    	QEIDisable(QEI1_BASE);
    	QEIIntDisable(QEI1_BASE,QEI_INTERROR | QEI_INTDIR | QEI_INTTIMER | QEI_INTINDEX);
    
    	QEIConfigure(QEI1_BASE
    			,(QEI_CONFIG_CAPTURE_A_B | QEI_CONFIG_NO_RESET|QEI_CONFIG_CLOCK_DIR|QEI_CONFIG_SWAP|0x02E00)
    			,MaxPos);
    
    	QEIPositionSet(QEI1_BASE, initpos);
    
    	UARTprintf("\nQEI 1 Module Enable\nPosition set to %d\n\n",initpos);
    
    	QEIEnable(QEI1_BASE);
    
    }
    
    int main (void)
    {
    
    	Init();
    
    	InitPWM();
    
    	InitSSI0();
    
    	InitSSI2();
    
    	while(1)
    
    	{
    
    		ADCRead();
    
    		//Calculos();
    
    		PWM();
    
    		InitSSI0();
    
    		InitSSI2();
    
    		InitComunication();
    
    	}
    
    }
    
    
    void Timer0IntHandler(void)
    {
    	// limpa o timer
    	TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
    
    }
    
    
    void Timer1IntHandler(void)
    {
    	// limpa o timer
    	TimerIntClear(TIMER1_BASE, TIMER_TIMA_TIMEOUT);
    }
    

    Here's the .c code. About the SSI Master is sending and slave is getting all values, but SLave can't send to Master, i have to create an interruption. 

    Also i can only  get the information when i reset lol

  • Hello Victor

    In the QEISlave.c, I found the following code in InitSSI0. It seems that you wanted PORTF-Pin3 to be in output mode but Port-A got copied which is the Slave FSS pin

        GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_3);//ACC FSS pull-up
        GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_3,GPIO_PIN_3);

    Regarding the voltage on the PD6 pin being not 3.3V nor 0V, I can check the same on the TIVA C LaunchPad, but I am certain it would be 3.3V or 0V and nothing intermediary.


    Regards

    Amit

  • Past questions asked by Amit & myself remain unanswered - complicates our remote diagnosis - done in your behalf.

    You're weaving quite a tale here - initially w/PD6 and an abnormal hall sensor (reported) voltage of 2V8.  I challenged that reading - to silence.

    Amit's asked about your troublesome board - official or factory - no real answer there, either.

    And latest incarnations move from the earlier (agreed) PD2 (timer) now (seemingly) to PD6.  And now you report 2 new voltage readings - both far from normal/customary.

    Troubleshooting 101 follows:

    a) how sure are you of your measurement instrument?  has it been calibrated recently?

    b) if homebrew board - I'd bet on "missed" Vdd/Vss pins (at least some) and/or inadequate number/value of MCU bypass caps.  (these are not an option)

    c) have you measured for 3V3 @ your MCU's Vdd pins?  (each/every one of them?)  likewise have you ohmed out each/every MCU Vss pin?

    d) Amit questioned the "presence and connection" of some "hanger-on" component - which may have caused your non standard readings.  Again - silence. 

    e) returning to 2V8 (your report) from hall sensor - can you repeat that measurement but w/that sensor disconnected from the MCU - so that just the hall itself is being measured?  Most halls require a pull-up - 10K should be fine - and I'd route that to 3V3.  Also - many/most halls require a connection to 5V or 3V3 and to ground.  Is that how yours is handled? 

    f) Your introduction of a magnetic flux in the near vicinity of that hall device should cause it to change state.  I'd expect the voltage to move from the pull-up voltage level to very near ground.  Does this occur.  Again - perform this test with no connections to your MCU.

    The more variables which we can isolate - the faster this (simple) issue may be resolved.  But you really do have to pay more attention to detail - on this forum and in school or on the job.  Unanswered questions may drive your helpers away...

  • a) Measurement instruments are fine, im using a fluke 87 true rms.

    b) Im using a breadboard just to connect 1 acelerator as a voltage divider, reading inthe ADC, i use a dc voltage source to give 5V in a 4.7k resistor with a potenciometer of the acelerator being a 7.62kohms, giving me a range from 0 to 3V3 for the ADC.

    c) I mesured the Vdd MCU's and i get the 3V3 and grounds are ok. Also found out that all the pins that are unused are between 1.2-1.4V, probably because i already made them enable in the Init code, because later i was going to remove all the unnecessary code.

    d) Right now i dont have any components in the breadboard that im not using that may influence the signals.

    e) my sensor is this one

    http://www.vnsky.com/parts/1753868/55505-00-02-A.html?gclid=CIm6gZrclL8CFSXmwgodYEcAEw

    Its range for supply if from 4.75 to 24V, im using 5V. I'm using a 4.7kohm resistor and then a an other voltage divider. and im probably thinking in using a voltage regulator for 12V so i can get better results form this sensor and use a voltege divider to get it to 3V3.

    f) I have made all those tests previously to avoid damagind MCU's ports.

    All i think its happening is that sinse im using lanchboard, if i Enable the ports they stop being zero and give an output of 1.2V while not being used on anything. PD6 was an exception because i gave function of PhA0 and the exit was still 1.2V, and whn i got my sensor on that port, the voltage dropped from 3V3 to 2V8, that's what happened.

    Im using TM4C123GXL launchpad with the H6PMI MCU.

    I hope this is the answer to all your doubts

  • Want to acknowledge your detail - greatly assists - you must realize "never" could Amit/this guy have known (or guessed) such.

    The (new) mention of a V. Divider upon the hall output clarifies the 2V8 reading.  We simply pull our halls up to 3V3 - I doubt that running from much higher voltage gains much.  (but I've not (yet) read your hall data sheet)

    Have been up/active here for quite awhile (too early, today) - I'm done for next few hours now but will respond further when we reach client destination...  Again - your detail aids greatly - recall "you" know your use/set-up - those remote - not so much!   (you've got to think (somewhat) about your remote assets...)

    Past you only mentioned "hall" as the sensor.  Now - we read of "accelerometer" (or potentiometer) - but that's very much unclear!  (our group happens to provide special equipment for a "real Accelerator" (@ Argonne) doubt that's yours...)

    All MCU pins "reading" on/about 1V2 are "outside" my expectations.  You say you've "enabled" the ports - do not they "normally" default as gpio inputs - perhaps w/weak pull-up Rs?  If instead - those pins are floating - "all bets are off" on any/all measurements.  (i.e. pull such pins up or down - do not let them float)  Again - (Arnold)/this guy - we'll be back!...

  • I've read back thru this data forest - not sure I've properly grasped (all) of the movement.  Let's review your initial, defining post, "I'm a beginner and I'm trying to use PD2 as a digital input to check if its HIGH or LOW and make a counter to implement a Speedometer."

    Initially you requested assistance for a relatively simple, speed measurement.  First Amit (via QEI) and then I (via a Timer pair) responded.  I believed the 2 Timer method to be faster, simpler.  Initially you agreed - then (multiple) changes and expansion to SSI or 2nd board arrived - I'm confused. (perhaps others, too)

    You've just now revealed use of an, "Accelerator" (pedal - pot) that's new info - is it not?  Adding (fast/often) to any project spec often proves disruptive.  (I write our tech contracts to clearly alert clients that many changes are not, "quick/easy."   (clients always make such claim)  Receiving such change data "late in the game" (as here) may invalidate much of the earlier design - thus is to be discouraged and ideally, avoided!)

    Listed early was a reasonable explanation of a method to read pulses per unit time.  This involves use of 2 Timers - with one - acting as a counter - receiving your hall sensor signals.  (sensor pulled up to 3V3)  Moving away from KISS - (timers) as suggested earlier - opened this (expanding) can of (QEI-SSI-ADC accelerated) worms. 

  • I did take a look at the sensor.  A few key points

    • Minimum operating voltage 4V75
    • Internal pull-up
    • Minimum High output voltage Vdd-2 (Obviously load dependent, and I did not see an indication of the dependence but it is specified for a 20mA max draw)
    • maximum low output 0V6 at 20mA

    I'd use a schmitt trigger inverter-filter-inverter combination to clean up the signal and level translate it rather than a resistor divider. Even if the inputs to the micro are 5V tolerant I wouldn't want to put an external signal directly on the micros input pin.

     

    Robert

  • I understand i asked more than one thing in this post, but it happens when you see new solutions for your problem.

    I think the first problem here is the lack of good information about programming these microcontrollers.

    Second is that, as a beginner the stellaris launchpad tutorials are not enough for someone to start.

    As a portuguese its hard to me to understand some of the solutions given.

    I propose to close this poll and eventually open one for each theme if i need.

    I'm sorry if i digressed on the main topic, but one thing led an other.

  • In defense of TI I find their documentation generally useful with the full information needed to program the microcontroller.  There are holes in the documentation but they are generally small.

    Also from the information you've given so far I strongly suspect your problems arise from simple electrical design issues not software.  1V4 on a 3V3 digital I/O should be causing you alarm.

    Language can be an issue.  I think you will find most people will be patient and attempt to find clear explanations for you.

    Robert

  • @Victor,

    You've done quite well for someone early in this game.  (that's not Amit's, Robert's or my case...)

    And your language skills are good - and will only improve.

    I commented on your project's, "creepage" to bring that to your attention.  This happens often - and most always leads to unpleasantness.  Best to spend bit more time in planning - then post your issues here - usually one MCU Peripheral per post.  (this helps your responders - and makes, "categorization" of your post much easier - so that others may later find & review it)

    Note that you've got 3 votes "concerned" re: 1V2-1V4.  I'm still betting those readings are meaningless - signal that the pin is an input and "floating."

    Bon chance, mon ami.  Closest I came to Portugal was Rota (not Madrid) Spain.  Beautiful & great/fun people...

  • Returning to the main subject. I solved the hall sensor problem, using a 74LS07N, open collector buffer, with a pull-up to 3.3V.

    My problem is, i'm still trying to use the QEI module.

    I used this:

    QEIEnable(QEIBASE_0);

    QEIConfigure(QEIBASE_0, (QEI_CONFIG_CAPTURE_A | QEI_CONFIG_NO_RESET | QEI_CONFIG_CLOCK_DIR | QEI_CONFIG_NO_SWAP), 1000);

    QEIVelocityConfigure(QEIBASE_0, QEI_VELDIR_1, 1000000);

    QEIVelocityEnable (QEIBASE_0);

    I'm going to use the sensor in Pha (only 1 sensor), clock_dir mode. I suppose i need to use the QEIConfigure function to define the mode, but i dont know why it asks the maximum position value.

    Do i need to define the timer interruption outside to call VelocityGet? Does it depend on the next instruction, last parameter?

    QEIVelocityConfigure(QEIBASE_0, QEI_VELDIR_1, 1000000);

    The last parameter is the timer?

    All this to know the rpm, using the given formula.

    rpm = (clock * (2 ^ VELDIV) * SPEED * 60) ÷ (LOAD * ppr * edges)

    Also i supose the edges counted in my system is only 1, because im only using 1 sensor.

    Again datasheet mencioned CAPMODE clear gives 2 edges and CAPMODE set 4. I dont know where to define this tipe of CAPMODE, and im only using half because its only 1 sensor.

  • Victor Azevedo said:
    Returning to the main subject

    And a, "QEI-free" method was past outlined and seemingly accepted.  Warnings were raised re: Complexity of QEI with an incomplete signal implementation.

    Your own words now state, "All this to know the rpm, using the given formula!"

    Did not your unexplained, "rejection/reversal from KISS" cause, "All of this?"  (hard to feel sorry...)

  • Victor Azevedo said:
    Returning to the main subject. I solved the hall sensor problem, using a 74LS07N, open collector buffer, with a pull-up to 3.3V

    Congratulations.

    You don't need to use open collector and pull-up here.  A normal drive will work.

    I would still suggest using a Schmitt trigger input and filtering. However, this will mostly work and let you solve your other problems.

    Victor Azevedo said:

    QEIVelocityConfigure(QEIBASE_0, QEI_VELDIR_1, 1000000);

    The last parameter is the timer?

    The last parameter is the time the input pulses are counted for.  The TIVAWare documentation states this is the number of clock ticks but does not state which clock.  Presumably that is in the chip documentation.  The TIVAWare documentation does assume knowlwdge of the actual chip.

    Victor Azevedo said:

    Also i supose the edges counted in my system is only 1, because im only using 1 sensor.

    Again datasheet mencioned CAPMODE clear gives 2 edges and CAPMODE set 4. I dont know where to define this tipe of CAPMODE, and im only using half because its only 1 sensor.

    Depending on how the QEI hardware is designed you could count rising edges, falling edges or both.  IC documentation again.

    Victor Azevedo said:
    All this to know the rpm, using the given formula

    You get to choose where your compexity is.  Either in a complex peripheral or in designing interrupt routines to deal with proper sampling.  In the case of an interrupt you have to check for overflow and ensure small amounts of jitter.  In the case of the complex peripheral you must get it set up correctly. 

    There are advantages to both.

    Robert