We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
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.