Jump to content
43oh

Square wave generator


Recommended Posts

I've coded a very simple square wave generator. It uses the buttons on P1.0 eh... ooopps... PB5 and PB0 (the two first buttons on the LarsLCD board), and prints the kHz value on the LarsLCD. It should run without the LCD also. The output is on PA2 (bottom right).

square-wave-gen.jpg

The LCD library is from CorB's post and is mainly his code by now. The generator code is adapted from the example timer code in the project documentation. If you have input on ways to write it better (button presses etc), I'm very happy to receive feedback.

 

#include <stdint.h>

#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_ints.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/ssi.h"
#include "driverlib/sysctl.h"
#include "driverlib/interrupt.h"
#include "driverlib/timer.h"
#include "glcd_hwSPI.h"

void PortBIntHandler(void);

#define SSI_CLK					GPIO_PIN_4
#define SSI_TX					GPIO_PIN_7
#define GPIO_PB4_SSI2CLK        0x00011002
#define GPIO_PB7_SSI2TX         0x00011C02

volatile int btn1 = 0;

int main(void) {

	unsigned long ulPeriod;

	SysCtlClockSet(
			SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ
					| SYSCTL_OSC_MAIN);

	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
	GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_2);

	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
	GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE,
			GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3);

	SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI2);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
	// CS ENABLE
	GPIOPinTypeGPIOOutput(GPIO_PORTE_BASE, GPIO_PIN_5);
	// CS LOW
	GPIOPinWrite(GPIO_PORTE_BASE, GPIO_PIN_5, 0);

	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);

	GPIOPinConfigure(GPIO_PB4_SSI2CLK);
	GPIOPinConfigure(GPIO_PB7_SSI2TX);

	GPIOPinTypeSSI(GPIO_PORTB_BASE, SSI_CLK | SSI_TX);
	//
	// Configure SSI2
	//
	SSIConfigSetExpClk(SSI2_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_0,
			SSI_MODE_MASTER, SysCtlClockGet() / 2, 16);
	//
	// Enable the SSI module.
	//
	SSIEnable(SSI2_BASE);

	LCD_Init();

	SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
	TimerConfigure(TIMER0_BASE, TIMER_CFG_32_BIT_PER);

	ulPeriod = (SysCtlClockGet() / 1000) / 2;
	TimerLoadSet(TIMER0_BASE, TIMER_A, ulPeriod - 1);

	IntEnable(INT_TIMER0A);
	TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
	IntMasterEnable();

	TimerEnable(TIMER0_BASE, TIMER_A);

	// Set up IO
	GPIOPinTypeGPIOInput(GPIO_PORTB_BASE, GPIO_PIN_0);
	GPIOPadConfigSet(GPIO_PORTB_BASE, GPIO_PIN_0, GPIO_STRENGTH_2MA,
			GPIO_PIN_TYPE_STD_WPU);
	GPIOPinTypeGPIOInput(GPIO_PORTB_BASE, GPIO_PIN_5);
	GPIOPadConfigSet(GPIO_PORTB_BASE, GPIO_PIN_5, GPIO_STRENGTH_2MA,
			GPIO_PIN_TYPE_STD_WPU);

	writeString(0, 0, "Signal generator");

	int f = 1;

	while (1) {

		int pressed = 0;

		if (!GPIOPinRead(GPIO_PORTB_BASE, GPIO_PIN_5)) {
			GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3,
					GPIO_PIN_1);
			SysCtlDelay(1000000);
			GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3,
					0);
			f -= 1;
			pressed = 1;
		} else if (!GPIOPinRead(GPIO_PORTB_BASE, GPIO_PIN_0)) {
			GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3,
					GPIO_PIN_2);
			SysCtlDelay(1000000);
			GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3,
					0);
			f += 1;
			pressed = 1;
		}

		if (pressed) {
			if (f < 0) {
				f = 1;
			} else if (f > 999) {
				f = 999;
			}
			ulPeriod = (SysCtlClockGet() / (f * 1000)) / 2;
			TimerLoadSet(TIMER0_BASE, TIMER_A, ulPeriod - 1);
		}

		setcharmode(1);
		writeInt(20, 2, f, 1);
		setcharmode(0);
		writeString(70, 3, "kHz");
		writeString(0, 7, " -    +  ");

		pressed = 0;
	}

}

void Timer0IntHandler(void) {
	// Clear the timer interrupt
	TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);

	// Read the current state of the GPIO pin and
	// write back the opposite state
	if (GPIOPinRead(GPIO_PORTA_BASE, GPIO_PIN_2)) {
		GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_2, 0);
	} else {
		GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_2, GPIO_PIN_2);
	}
} 

 

Files are attached, including the LCD library. I've adapted it to use header-files.

sq-wav-gen.zip

post-704-14264605179686_thumb.jpg

Link to post
Share on other sites

Great job.

 

Do you have some specs?

Can you give some scoop image from the wave? That would be nice.

 

What about

 

SysCtlClockSet(SYSCTL_SYSDIV_2_5, SYSCTL_USE_PLL | SYSCTL_OSC_MAIN_SYSCTL | SYSCTL_XTAL_16MHZ); 

 

This give 80Mhz, right? Is that usable?

 

 

Thank you.

 

 

Edit. Thank you for the images above and under

Link to post
Share on other sites

The code in this post is using the timer, so I'm not able to get it as high. I haven't tried to push the limit. Here's a scope picture at 200kHz. Seems the periods vary a bit. I'm not connecting the probe directly on the board, but through some wires that probably add some noise and capacitance. May be the blame for slightly off signal. 

 

post-704-14264605179847_thumb.png

 

In another post, I'm maxing it at 40MHz (80MHz CPU-clock), but it doesn't look like a square-wave, either because of my scope or because of the bandwidth limitations of the chip itself. You can see some images of faster signals there. 

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...