so im trying to make a frequency counter with a nucleoSTM32F429zi and i have a few issuse firstly im using a PWM output through a low pass filter to make a sine wave. that works fine however at the end of the project i have to desplay the frequance on an LCD this is where my problems i have an LCD connected properly. but when the PWM is active there is no output to either putty or the LCD i am also unable to send anymore than a single character at a time and i need a string to show the frequancy. please advise me on what is wrong
#include "mbed.h"#include "LCD.h"#include <cstdio>#include <stm32f4xx.h>
//INCLUDE THE HEADER FILE FOR THIS MCU FAMILY //Define an instance of SPI - this is a SPI master deviceSPI spi(PA_7, PA_6, PA_5); // Ordered as: mosi, miso, sclk could use forth parameter ssel
//We often use a separate signal for the chip select. It is VITAL that for each SPI port, only ONE SPI slave device is enabled.DigitalOut cs(PC_6); // Chip Select for Basic Outputs to illuminate Onboard FPGA DEO nano LEDs CN7 pin 1
// **************************************************************************// ******************** NB the following line for F429ZI ******************** // * The following line is essential when using this ribbon connector *// **************************************************************************DigitalIn DO_NOT_USE(PB_12); // MAKE PB_12 (D19) an INPUT do NOT make an OUTPUT under any circumstances !!!!! ************* !!!!!!!!!!! // This Pin is connected to the 5VDC from the FPGA card and an INPUT that is 5V Tolerant// **********************************************************************************************************
// **************************************** Function prototypes *********************************************uint16_t read_switches(void); //Read 4 Sliding switches on FPGA (Simulating OPTO-Switches from Motor(s)uint16_t spi_readwrite(uint16_t data); // **********************************************************************************************************
// **********************************************************************************************************// Main function // ********************************************************************************************************** //this file contains the definitions for register addresses and values etc...
int initPWM(void){
SystemCoreClockUpdate(); //ENABLE PORT(S) RCC->AHB1ENR|=RCC_AHB1ENR_GPIOBEN; //GPIO B clock enable //CONFIGURE PORT PIN FUNCTIONS GPIOB->MODER&=~(3u<<(2*0)); //clear pin functions on GPIOB GPIOB->MODER|=(1u<<(2*0)); //set new pin functions on GPIOB RCC->APB1ENR|=RCC_APB1ENR_TIM2EN; //timer 2 clock enabled TIM2->DIER|=TIM_DIER_UIE; //timer uptdate interrupt enabled //APB clock is Fcy/2 = 180MHz/2 = 90MHz TIM2->PSC=256-1; //divide APB clock by 256 = 90MHz/256 = 351kHz TIM2->ARR=3287; //counter reload value, gives a timer period of 100ms when F_APB = 90MHz and PSC = 256 TIM2->CNT=0; //zero timer counter NVIC->ISER[0]|=(1u<<28); //timer 2 global interrupt enabled TIM2->CR1|=TIM_CR1_CEN; //start timer counter while(1) //ENTER 'FOREVER' LOOP - THIS LOOP WILL NEVER EXIT { //FOREVER LOOP IS NOW EMPTY (MCU CAN BE PUT TO SLEEP HERE) }//END OF FOREVER LOOP}//end mainvoid TIM2_IRQHandler(void) //TIMER 2 INTERRUPT SERVICE ROUTINE{ TIM2->SR&=~TIM_SR_UIF; //clear interrupt flag in status register GPIOB->ODR^=(1u<<0); //XOR GPIOB output data register to invert the selected pin}
void lcd_delayus(unsigned int us) //blocking delay for LCD, argument is approximate number of micro-seconds to delay{ unsigned char i; while(us--) { for(i=0; i<SystemCoreClock/4000000; i++); }}void WaitLcdBusy(void){ lcd_delayus(1); //3ms blocking delay}void set_LCD_data(unsigned char d){ LCD_PORT->BSRR=(0xff<<(LCD_D0_pin+16)); //clear data lines LCD_PORT->BSRR=(d<<LCD_D0_pin); //put data on lines}
void LCD_strobe(void) //10us high pulse on LCD enable line{ lcd_delayus(10); set_LCD_E(); lcd_delayus(10); clr_LCD_E();}
void cmdLCD(unsigned char cmd) //sends a byte to the LCD control register{ WaitLcdBusy(); //wait for LCD to be not busy clr_LCD_RS(); //control command clr_LCD_RW(); //write command set_LCD_data(cmd); //set data on bus LCD_strobe(); //apply command}
void putLCD(unsigned char put) //sends a char to the LCD display{ WaitLcdBusy(); //wait for LCD to be not busy set_LCD_RS(); //text command clr_LCD_RW(); //write command set_LCD_data(put); //set data on bus LCD_strobe(); //apply command}
void initLCD(void){ SystemCoreClockUpdate(); RCC->AHB1ENR|=RCC_AHB1ENR_GPIOBEN; //enable LCD port clock //CONFIG LCD GPIO PINS LCD_PORT->MODER&=~( //clear pin direction settings (3u<<(2*LCD_RS_pin)) |(3u<<(2*LCD_RW_pin)) |(3u<<(2*LCD_E_pin)) |(0xffff<<(2*LCD_D0_pin)) ); LCD_PORT->MODER|=( //reset pin direction settings to digital outputs (1u<<(2*LCD_RS_pin)) |(1u<<(2*LCD_RW_pin)) |(1u<<(2*LCD_E_pin)) |(0x5555<<(2*LCD_D0_pin)) );
//LCD INIT COMMANDS clr_LCD_RS(); //all lines default low clr_LCD_RW(); clr_LCD_E(); lcd_delayus(25000); //25ms startup delay cmdLCD(0x38); //Function set: 2 Line, 8-bit, 5x7 dots cmdLCD(0x0c); //Display on, Cursor blinking command cmdLCD(0x01); //Clear LCD cmdLCD(0x06); //Entry mode, auto increment with no shift}
void LCDdelay (int time);
int send_to = LCD;
unsigned short SPIout;
void send_LCD(float Q){ cmdLCD(LCD_LINE1); send_to = LCD; printf("Volts: %.3fV\n\n", Q); }
float MISO(PA_6);
int main(){ cs = 1; // Chip must be deselected, Chip Select is active LOW spi.format(16,0); // Setup the DATA frame SPI for 16 bit wide word, Clock Polarity 0 and Clock Phase 0 (0) spi.frequency(1000000); // 1MHz clock rate initLCD(); initPWM(); while(1){ // start infinate loop float Volts; SPIout = MISO; Volts = SPIout*3.3f/4095.0f; //UART_Display(Volts); send_LCD(Volts); int d, c; for (c = 1; c <= 1000; c++) for (d = 1; d <= 1000; d++) {} LCD_CLR(); }
while(true) //Loop forever Knight Rider Display on FPGA { //Read switch state and write to PuTTY read_switches(); //LED Chaser display KIT lives on! for (uint32_t i=1;i<=128;i*=2) { spi_readwrite(i); wait_ms(20); } for (uint32_t i=128;i>=1;i/=2) { spi_readwrite(i); wait_ms(20); } //Wait for 1 second wait_ms(1000); } } // **********************************************************************************************************// Function to read back the state of the switches//// uint16_t read_switches(void)// Return data - the data returned from the FPGA to the MCU over the SPI interface (via MISO)// **********************************************************************************************************
uint16_t read_switches(void){ uint16_t sw_val = spi_readwrite(0); //Turn off all LEDs + read switches (in one full-duplex transaction)
if (sw_val&(1<<0)){ printf("Switch 0 :"); } if (sw_val&(1<<1)){ printf("Switch 1 :"); } if (sw_val&(1<<2)){ printf("Switch 2 :"); } if (sw_val&(1<<3)){ printf("Switch 3 :"); } if (sw_val>0) { printf("\r\n"); } return sw_val; }
// **********************************************************************************************************// uint16_t spi_readwrite(uint16_t data)//// Function for writing to the SPI with the correct timing// data - this parameter is the data to be sent from the MCU to the FPGA over the SPI interface (via MOSI)// return data - the data returned from the FPGA to the MCU over the SPI interface (via MISO)// **********************************************************************************************************
uint16_t spi_readwrite(uint16_t data) { cs = 0; //Select the device by seting chip select LOW uint16_t rx = (uint16_t)spi.write(data); //Send the data - ignore the return data wait_us(1); //wait for last clock cycle to clear cs = 1; //De-Select the device by seting chip select HIGH return rx;}
Isn't there a code formatting tool? How will it leave initPWM()?
Software delays might need to use volatile variables so they aren't optimized away.
Might have to debug your own software/hardware, got a unique mix here.
Get a scope, check the signalling to the display vs expectations.
Use the debugger, step your code, understand what it is doing, and not doing.