STM32 Output MCO configuration - clock

I try to configure my MCO ouput on my STM32f103, only with STD periph lib.
here is my code:
void OutputMCO() {
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
/* Output clock on MCO pin ---------------------------------------------*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// pick one of the clocks to spew
//RCC_MCOConfig(RCC_MCOSource_SYSCLK); // Put on MCO pin the: System clock selected
//RCC_MCOConfig(RCC_MCOSource_HSE); // Put on MCO pin the: freq. of external crystal
//RCC_MCOConfig(RCC_MCOSource_PLLCLK_Div2); // Put on MCO pin the: System clock selected
}
I have an issue here:
// pick one of the clocks to spew
//RCC_MCOConfig(RCC_MCOSource_SYSCLK); // Put on MCO pin the: System clock selected
//RCC_MCOConfig(RCC_MCOSource_HSE); // Put on MCO pin the: freq. of external crystal
//RCC_MCOConfig(RCC_MCOSource_PLLCLK_Div2); // Put on MCO pin the: System clock selected
None of the 3 possibilities are working on my code. This code was found on internet. Do you know where should I find correct parameters ? The definition of RCC_MCOSource doesn't really help me
Thank you

I found the solution in file stm32f10x_rcc:
#define RCC_MCO_NoClock ((uint8_t)0x00)
#define RCC_MCO_SYSCLK ((uint8_t)0x04)
#define RCC_MCO_HSI ((uint8_t)0x05)
#define RCC_MCO_HSE ((uint8_t)0x06)
#define RCC_MCO_PLLCLK_Div2

For libopencm3 it is a problem of the header files as well.
The configuration bits for which clock should be taken for the MCO are in the Clock configuration register (RCC_CFGR) at position [27:24] (at least for STM32f0 series).
If you now try to configure the MCO to SYSCLK like the following it doesn't work.
RCC_CFGR = (RCC_CFGR & ~RCC_CFGR_MCO_MASK) | RCC_CFGR_MCO_SYSCLK;
If you take a look at the libary file rcc.h you find a line:
#define RCC_CFGR_MCO_SYSCLK 4
so you are writing on bit position 2 instead of 26.
Solution:
RCC_CFGR = (RCC_CFGR & ~(RCC_CFGR_MCO_MASK << 24)) | (RCC_CFGR_MCO_SYSCLK << 24);

Related

PLL Init function in STM32F429 to configure max frequency (180Mhz)

I want to configure PLL in STM32F429 to its max frequency (180Mhz) without using STMCube-generated configurations. I am using my own register definitions like this
#define RCC_CFGR (*((volatile uint32 *)0x40023808))
and my own SET_BIT()/CLEAR_BIT() macros
My questions are:
1- Is this procedure correct?
2- How can I check if it is working?
3- May the MCU can not handle this speed (reading/writing in registers)?
#define PLL_M 16
#define PLL_N 360
#define PLL_P 2
#define PLL_Q 7
void PLL_init(void)
{
/* System Init */
/* HSI ON */
SET_BIT(RCC_CR, HSION);
/* Reset CFGR register */
RCC_CFGR = 0x00000000 ;
/* Reset PLLCFGR register */
RCC_PLLCFGR = 0x24003010;
/* Reset HSEON, CSSON and PLLON bits */
RCC_CR &= (uint32_t)0xFEF6FFFF;
/************* SetSysClock ************/
RCC_PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16)| (PLL_Q << 24);
/* PLL clock Source HSI or HSE */
CLEAR_BIT(RCC_PLLCFGR, PLLSRC);
/* APB1 PWR Enable*/
SET_BIT(RCC_APB1ENR, PWREN);
/* Select regulator voltage output Scale 1 mode, System frequency up to 180 MHz */
SET_BIT(PWR_CR, VOS0);
SET_BIT(PWR_CR, VOS1);
/* AHB div 1 */
CLEAR_BIT(RCC_CFGR,HPRE3);
CLEAR_BIT(RCC_CFGR,HPRE0);
/* APB2 Div = 2*/
CLEAR_BIT(RCC_CFGR,PPRE20);
CLEAR_BIT(RCC_CFGR,PPRE21);
SET_BIT(RCC_CFGR, PPRE23);
/* APB 1 Div = 8 */
CLEAR_BIT(RCC_CFGR, PPRE10);
SET_BIT(RCC_CFGR, PPRE11);
SET_BIT(RCC_CFGR, PPRE12);
/* SET PLL ON */
SET_BIT(RCC_CR, PLLON);
/* Check PLL is ready */
while(BIT_IS_CLEAR(RCC_CR,PLLRDY));
/* Enable the Over-drive to extend the clock frequency to 180 Mhz */
SET_BIT(PWR_CR, ODEN);
while(BIT_IS_CLEAR(PWR_CSR,ODRDY));
SET_BIT(PWR_CR, ODSWEN);
while(BIT_IS_CLEAR(PWR_CSR,ODSWRDY));
SET_BIT(FLASH_ACR, PRFTEN);
SET_BIT(FLASH_ACR, ICEN);
SET_BIT(FLASH_ACR, DCEN);
FLASH_ACR |= FLASH_ACR_LATENCY_5WS;
/* Select the main PLL as system clock source */
CLEAR_BIT(RCC_CFGR, SW0);
SET_BIT(RCC_CFGR, SW1);
/* Wait till the main PLL is used as system clock source */
while(!BIT_IS_CLEAR(RCC_CFGR,SWS0) && !BIT_IS_SET(RCC_CFGR,SWS1) ); /* Loop till is Set */
}
I did exactly this thing on my STM32F746 - set 216MHz with registers. It looks very similar to mine. Not observing any obvious things. You wait for all ready flags and all. Overdrive and overdrive switching are there, flash wait states are there.
How to check if it's working - timer is an easy idea. Timer that is clocked by a system clock with some prescaler and that outputs PWM to some pin. Given the configuration of the timer is set by you, you should know what output frequency to expect. You can set timer parameters in such a way that you expect timer-interrupt-toggle an LED every 1s.
The MCU should handle it OK if all prescalers for AHB/APB are within limits, as well as Flash latency is set correctly. Which seems to be the case.
If you want to compare the logic with what I do with STM32F746 (which looks almost identical in terms of how you do it), you can check it in this rcc.c file of mine. It definitely works, I tested it.

What is wrong with this PIC16F877A HCSR04 example?

I am working on distance sensor with PIC16F877A.
I am using MPLAB IDE AND XC8 compiler.
My goal is to gradually turn on the right leds at certain distance levels, but the leds are blinking unstable. What am I doing wrong? distance/5
When it measures 5 cm, it is 5/5 and the result is 1 and 1 led is on.
When it measures 10 cm, it is 10/5 and the result is 2 and 2 leds are on.
When you measure 15 cm, it is 15/5 and the result is 3 and 3 LEDs are on.
When you measure 20 cm, it is 20/5 and the result is 4 and 4 leds are on.
If the distance is less than 5 cm or above 20 cm, no led lights are on
https://i.stack.imgur.com/fFKQg.png
#include <xc.h>
#include <pic16f877a.h>
#pragma config FOSC = XT // Oscillator Selection bits (XT oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = OFF // Brown-out Reset Enable bit (BOR disabled)
#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
#define _XTAL_FREQ 4000000
#define trigger RC2
#define echo RC3
int calc_distance();
int calc_distance()
{
int distance=0;
trigger=1;
__delay_us(10);
trigger=0;
while(!echo); // normally the echo pin is logic 0. If we toggle the zero and throw it into the while, it returns idle until the echo arrives (until the signal becomes logic 1).
TMR1ON=1;//In the upper loop, while returning the command empty, echo comes and exits the upper loop and timer1 is activated.
while(echo);
TMR1ON=0;//
distance=TMR1/58;
return distance;
}
void main(void)
{
int dist=0; // Create Distance Variable
TRISB = 0x00; // Set PORTB To Be Output Port (All The 8 Pins)
PORTB = 0x00; // Set PORTB To Be LOW For initial State
TRISC2 = 0; // Set RC2 To Be Output Pin ( Trigger )
RC2 = 0;
TRISC3 = 1; // Set RC3 To Be Input Pin ( Echo )
//--[ Configure Timer Module To Operate in Timer Mode ]--
// Clear The Pre-Scaler Select Bits
T1CKPS0=0;
T1CKPS1=0;
TMR1CS=0;// Choose The Local Clock As Clock Source
while(1)
{
calc_distance();
dist = calc_distance()/5;
if(dist==1)
{PORTB = 0x01; __delay_ms(50);}
if(dist==2)
{PORTB = 0x03; __delay_ms(50);}
if(dist==3)
{PORTB = 0x07; __delay_ms(50);}
if(dist==4)
{PORTB = 0x0F; __delay_ms(50);}
else
{PORTB = 0x00; __delay_ms(50);}
}
return;
}

Why does my usb HID output rubbish? STM32Cube

I'm trying to make a force feedback wheel, but software isn't my cup of tea.
This is supposed to toggle button 0 and it doesn't.
typedef struct{
uint8_t buttons;
int8_t relativeMvt;
}steer_t;
steer_t steer = {0, 0};
while (1)
{
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
if(steer.buttons) steer.buttons = 0b00000000;
else steer.buttons = 0b00000001;
USBD_CUSTOM_HID_SendReport(&hUsbDeviceFS, steer, sizeof(steer));
HAL_Delay(500);
}
My Report descriptor (this is the first time I'm using one):
Running that code, the buttons are static "ON" like so:
They DO change (randomly) only when the "relativeMvt" variable is changed, very weird.
What I've tried:
Swap relativeMvt and buttons in the typeDef
Check the report descriptor size etc
Cry
#define USBD_CUSTOMHID_OUTREPORT_BUF_SIZE 2
#define USBD_CUSTOM_HID_REPORT_DESC_SIZE 45
#define CUSTOM_HID_EPIN_SIZE 2
What do I have to change to make it work? Thanks!
I've solved it. I was missing:
#include "usbd_customhid.h"
and I forgot the "&" when passing my variables:
USBD_CUSTOM_HID_SendReport(&hUsbDeviceFS, &steer, sizeof(steer));

STM32F4 Timing Problem with systick after switching IDE (coocox to TrueStudio)

I am working on a weird problem: As a part of my project, I migrated a firmware from CooCox to TrueStudio. Both, CooCox and TrueStudio automatically create some standard files while creating a project for a specific Microcontroller. The Microcontroller used here is the STM32F407VGT6. I am using ms - delay and s - delay which are derived from the µs - Delay function I will show you.
*edit2: I should mention, that the original project is a pure C project. I am trying to make the Project a C++/C project in TrueStudio.
What I will try now is to migrate the firmware into a TrueStudio pure C project and see if the problem still exists.
I will inform you about the results
**Results: The problem is actually gone now in the pure C Project, but I would really like to implement classes etc using C++. Any ideas how to solve this?
**
*
The initializing systick code is (HCLK Frequency = 168MHz).
*edit1: the HCLK Frequency equals the SYSCLK *
void systick_init(void){
RCC_ClocksTypeDef RCC_Clocks;
Systick_Delay=0;
RCC_GetClocksFreq(&RCC_Clocks);
SysTick_Config((RCC_Clocks.HCLK_Frequency / 1000000) - 1);
}
The function for the 1µs Delay looks like this:
void delay_us(volatile uint32_t delay)
{
Systick_Delay = delay;
while(Systick_Delay != 0);
}
The Systick Handler contains the following Code:
void SysTick_Handler(void)
{
// Tick für Delay
if(Systick_Delay != 0x00)
{
Systick_Delay--;
}
}
When I create a .hex file to flash the µC with using Coocox, the timing function works (with some minor accuracy mistakes that don't bother me).
When I create the .hex file with TrueStudio, the delays have massive inaccuracys. For example, a delay of 500ms becomes a delay of roughly 2s.
Since the Code is written dependant on the actual HCLK_Frequency, I can't understand the mistake and in my understanding, even if the HCLK should differ, the 1µs Delay should still take about 1µs.
My next step will be comparing the automatically created system files, but maybe anyone has a different approach / another idea?
*edit 3: I normally include my systick - header with the command ' extern "C" '. So my systick source file is a .c file. When I rename the file to systick.cpp, and I include the header without 'extern "C"', the delay function does not work at all. Maybe, that helps with the solution?
*
You are either running off a different clock or have different PLL settings. Looks like your clock speed is 1/4 of what you had before.
The basic startup code provided does not always set the maximum speed for the board. Have a look in some of the examples in the stm32cube.zip code. You will find some System Clock Configuration code for your board which will select the correct clock and pll settings. (this will be in your code somewhere as well).
Look in main.c under stm32cubef4/projects/STM32F4-Discovery\Demonstrations\src.
You will find the following code which sets up the clock:
/**
* #brief System Clock Configuration
* The system Clock is configured as follow :
* System Clock source = PLL (HSE)
* SYSCLK(Hz) = 168000000
* HCLK(Hz) = 168000000
* AHB Prescaler = 1
* APB1 Prescaler = 4
* APB2 Prescaler = 2
* HSE Frequency(Hz) = 8000000
* PLL_M = 8
* PLL_N = 336
* PLL_P = 2
* PLL_Q = 7
* VDD(V) = 3.3
* Main regulator output voltage = Scale1 mode
* Flash Latency(WS) = 5
* #param None
* #retval None
*/
static void SystemClock_Config(void)
{
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_OscInitTypeDef RCC_OscInitStruct;
/* Enable Power Control clock */
__HAL_RCC_PWR_CLK_ENABLE();
/* The voltage scaling allows optimizing the power consumption when the device is
clocked below the maximum system frequency, to update the voltage scaling value
regarding system frequency refer to product datasheet. */
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/* Enable HSE Oscillator and activate PLL with HSE as source */
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 8;
RCC_OscInitStruct.PLL.PLLN = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 7;
HAL_RCC_OscConfig(&RCC_OscInitStruct);
/* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
clocks dividers */
RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);
/* STM32F405x/407x/415x/417x Revision Z devices: prefetch is supported */
if (HAL_GetREVID() == 0x1001)
{
/* Enable the Flash prefetch */
__HAL_FLASH_PREFETCH_BUFFER_ENABLE();
}
}
I found the solution now!
For anyone having similar problems:
You need to declare the SysTick_Handler function as
extern "C" void SysTick_Handler(void)
{
//Tick für Delay
if(Systick_Delay != 0x00)
{
Systick_Delay--;
}
}
Now it is working like it is supposed to do.

MSP430 G2553 UART Baudrate 9600 16MHz clock Issues

I'm interfacing my G2553 to a standard LCD screen using UART. I got it working like a dream at 1MHz, but need the system to run at 16MHz for certain other peripherals. I got it very close to working at 16MHz but there is what I believe to be a baudrate error, as the screen will show almost what I sent it, but miss a character here or there or get a character incorrect. I'll take you through how I wrote my code to see if I made any errors.
The screen expects a baudrate of 9600, so I went to the table in my user guide:
So UCBRx = 1666
and UCBRSx = 6.
The expected % errors on this are actually better than what I was using at the 1MHz clock so I thought this would be OK.
This means UCBR0 = 130 and UCBR1 = 6 (This is just the HEX value of UCBRx spread over two 8-bit registers) and UCBRSx = 6.
Now to enter these I looked at what the user guide tells us about the UART modulation register:
(was going to make this pretty but I don't have the reputation to post images)
So my initialisation code ended up being:
if (CALBC1_16MHZ==0xFF) // If calibration constant erased
{
while(1); // do not load, trap CPU!!
}
DCOCTL = 0; // Select lowest DCOx and MODx settings
//setup DCO to 16MHZ
BCSCTL1 = CALBC1_16MHZ;
DCOCTL = CALDCO_16MHZ;
P1SEL |= BIT1 + BIT2 ; // P1.1 = RXD, P1.2=TXD
P1SEL2 |= BIT1 + BIT2;
UCA0CTL1 |= UCSSEL_2; // SMCLK
UCA0BR0 = 130; // 16MHz 9600
UCA0BR1 = 6; // 16MHz 9600
UCA0MCTL = UCBRS2 + UCBRS1; // modulation is 110b or 6
UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
However as I stated above this is almost there, for example if I try to display the string "Initialising..." which worked for my 1MHz 9600 baudrate settings, with 16MHz at these settings it might display "Initiali ng..." - something close but obviously some error in there that I don't want.
Thank you for any help you can provide on this.
According to the baud rate calculator at http://mspgcc.sourceforge.net/baudrate.html, UCA0MCTL is supposed to be 0x5B