STM32F103 using MISO pin when SPI in Half-Duplex mode - timer

I'm using STM32F103C8T6 with SPI1 remapped and in half-duplex mode (MISO pin unused by SPI). I'd like to use MISO pin (PB4) for PWM generation by TIM3 remapped but I can not get it working while SPI1 is clocked.
So is there a way to use MISO pin of SPI in half-duplex mode for other AF function while SPI remains clocked?
UPD. I found out that MISO pin can be used as GPIO when SPI in half-duplex master mode

Related

Programming the MCP4141 digital potentiometer in STM32CUBEIDE by SPI port

I am trying to program a Microchip MCP4141 digital potentiometer with the STM32CUBEIDE development environment using a NUCLEO F334R8 board. I am sending a 16 bit command through the SPI communications port. When I send the command byte with the data byte, I cannot notice voltage variations between the P0A and P0W terminals of the MCP4141.
Could you help me find the programming error? Thanks
uint8_t data[2];
data[0]=0x00;
data[1]=0x0F;
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4,GPIO_PIN_RESET);
HAL_SPI_Transmit(&hspi1, data, 2, 500);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4,GPIO_PIN_SET);
Usually when an SPI peripheral does not work, the commands are not received by the slave chip. This can have multiple reasons:
Incorrect wiring (MOSI, MISO, CLK lines)
Incorrect SPI mode (clock phase, clock polarity) --> check SPI settings in CubeMX
Slave chip is in Reset because of incorrect/floating EN or RST Pin
Can you probe the data and clock lines? Do you see a signal being transmitted?
Alternatively, can you successfully read anything from the chips internal memory e.g. the status register?

SPI COMM in Atmega328p

I am working on Atmega328p using Arduino Uno board, my task is SPI comm using register level,
can anybody explain what is meant by DD_MOSI is left shift "1<
I assume you are referring to the code examples on page 172 of the ATmega328p datasheet (http://ww1.microchip.com/downloads/en/DeviceDoc/ATmega48A-PA-88A-PA-168A-PA-328-P-DS-DS40002061A.pdf). In the example, they use DD_MOSI as a stand in for the bit position of the control bit for the pin associated with MOSI signal, which on the MCU in question is PortB[3]. So, when they have the line:
DDR_SPI = (1<<DD_MOSI)|(1<<DD_SCK);
You can translate that to fill in the associated port and bit shifts:
DDRB = (1<<DDB3)|(1<<DDB5); // Since SPI in on Port B, MOSI is the third pin and SCK is the 5th pin, see page 91-92

Why is the PLL not locking? Is my clock configuration correct?

I am using the stm32l412kb for UART communication. I am trying to configure the USART2 peripheral clock to a 72MHz frequency. The stm32, after reset, uses the MSI at 4MHz, which I then use the PLL to extend to 72MHz when reaching the peripheral.
The code holds at the first PLLRDY check, as the PLL I assume is not locking. Could this be due to a too high a frequency output? Have I configure everything correctly? How do I know that the PLL is then being used instead of the 4MHz MSI, or the 24MHz HSE?
'''
void configureClocks(){
/*Clock Configuration
* The MSI (at 4MHz) is used as system clock source after startup from Reset.
* */
/*Turning on the medium speed internal clock (making sure it's on)*/
RCC->CR |= RCC_CR_MSION;
RCC->CR |= RCC_CR_MSIPLLEN;
/*Waiting until clock is ready*/
while(!(RCC->CR & RCC_CR_MSIRDY));
/*Selecting the MSI (0010) as the MCU clock output*/
RCC->CFGR &= RCC_CFGR_MCOSEL_Msk;
RCC->CFGR |= (0b0010<<RCC_CFGR_MCOSEL_Pos);
/*Turn off PLL to allow to make changes*/
RCC->CR &= ~(RCC_CR_PLLON_Msk);
/*Make sure PLL is locked*/
while(!(RCC->CR & RCC_CR_PLLRDY));
/*At 4Mhz, (4*36/2 = 72Mhz)*/
RCC->PLLCFGR &= ~(RCC_PLLCFGR_PLLN_Msk | RCC_PLLCFGR_PLLM_Msk);
RCC->PLLCFGR |= (2 << RCC_PLLCFGR_PLLM_Pos) | (36 << RCC_PLLCFGR_PLLN_Pos);
/*Turning back on the PLL clock*/
RCC->CR |= RCC_CR_PLLON;
/*Waiting until clock is ready*/
while(!(RCC->CR & RCC_CR_PLLRDY));
/*Selecting the PLL (0101) as the microcontroller clock output*/
RCC->CFGR &= RCC_CFGR_MCOSEL_Msk;
RCC->CFGR |= (0b0101<<RCC_CFGR_MCOSEL_Pos);
/*Enabling the USART2 peripheral clock.*/
RCC->APB1ENR1 &= ~(RCC_APB1ENR1_USART2EN_Msk);
RCC->APB1ENR1 |= (0b1 << RCC_APB1ENR1_USART2EN_Pos);
/*Enabling the GPIOA port peripheral clock*/
RCC->AHB2ENR &= ~(RCC_AHB2ENR_GPIOAEN_Msk);
RCC->AHB2ENR |= (0b1 << RCC_AHB2ENR_GPIOAEN_Pos);
return;
}
'''
Your responses are always much appreciated,
Many thanks,
Harry
Update, thanks to comments:
The first PLL check has been changed from:
while(!(RCC->CR & RCC_CR_MSIRDY));
to:
while(RCC->CR & RCC_CR_MSIRDY);
However, the PLL check still gets stuck on the second one.
Please refer to the Reference Manual (pdf) section 6.2.3 "MSI clock", "Hardware auto calibration with LSE (PLL-mode)" and section 6.4.1 "Clock control register (RCC_CR)"
There is in your code:
RCC->CR |= RCC_CR_MSIPLLEN;
But before enabling PLL mode on the MSI clock you have two things to be done:
External low-frequency resonator or oscillator should be installed (e.g. 32768Hz clock quartz)
As said in the Bit 2 MSIPLLEN description: MSIPLLEN must be enabled after LSE is enabled (LSEON enabled) and ready (LSERDY set
by hardware).There is a hardware protection to avoid enabling MSIPLLEN if LSE is not
ready.
So, if you have LSE installed, first you have to turn it on, and wait until it ready:
RCC->BDCR |= (RCC_BDCR_LSEON);
/*Make sure LSE is ready*/
while(!(RCC->BDCR & RCC_BDCR_LSERDY));
But probably you don't have to use PLL function of the MSI, because USART much more tolerant to frequency deviations. Then MSI-PLL mode should be kept disabled.
STM32 MCUs have some protection mechanics to avoid wrongly switch the clock source. Some bits cannot be set until clock source is ready, or cannot be cleared if the clock source is in use. They are described in the reference manual in bit descriptions.
So, please, carefully compare all steps you're doing to the manual.
UPD
As pointed out in another answer
/*Turn off PLL to allow to make changes*/
RCC->CR &= ~(RCC_CR_PLLON_Msk);
/*Make sure PLL is locked*/
while(!(RCC->CR & RCC_CR_PLLRDY));
You cannot have PLL locked when it is disabled. So, the while-loop will run forever.
UPD2
Before enabling the PLL you forget to set up it's source (bits PLLSRC in PLLCFGR). I.e.:
// set MSI as the source for PLL
RCC->PLLCFGR = (RCC->PLLCFGR & ~RCC_PLLCFGR_PLLSRC_Msk) | RCC_PLLCFGR_PLLSRC_MSI;
After disabling the PLL with RCC->CR &= ~(RCC_CR_PLLON_Msk); wait until PLLRDY is cleared.
Your code does the opposite, waits until PLLRDY is set, meaning it's locked. But you've just disabled it, so it's not going to lock.
After setting up PLLCFGR, turn it back on, and wait until PLLRDY is set. This part looks OK in the code.
When the PLL is running at the required speed, you should set the System clock switch (RCC_CFGR_SW) to PLL instead of the Microcontroller clock output to have your system run on the PLL clock.
Microcontroller clock output does something else. It can be connected to an external pin, to output the clock signal for using it outside the MCU, e.g. to synchronise several MCUs.
I always use Cube to see the clock tree. I also use registers - but that tool is very convenient and it prevents many stupid errors as it will let you know if the values are outside the recommended ones.
PS it should be a comment but I wanted to put the picture. So please do not UV or accept

Can i use different timer channels when other channels (of the same timer) have i2c alternate function

My embedded device has i2c on the following pins
GPIO_2 => GPT0_CH2 => configured as i2c SDA
GPIO_3 => GPT0_CH3 => configured as i2c SCL
and i've set up the other channels as
GPIO_0 => GPT0_CH0 => configured as PWM Led
GPIO_1 => GPT0_CH1 => configured as PWM Fan
Can the following configuration work?
The PWM is running at 2khz with duty cycle from 0% to 100%.
Will it have any impact on the i2c behaviour?
I'm expecting they are using the same GPT so changing frequency leads to a disaster?
The PWM and the I2C module are connected to the GPIO output via an multiplexer. By configuring related registers in your microcontroller you can decide which output will be passed through to the GPIO. This block diagram shows a very simplified overview of the relations between peripheral modules, multiplexer and output:
By setting SEL to 0or 1 either IN0 or IN1 will be passed through to the GPIO pin.
So the answer is: No, your setting for the PWM frequency will not have any impacts on I2C behaviour.

Sparkfun SC16IS750 interrupt pin IRQ not working

I am facing problems using sc16is750 breakout board. I want to use the interrupt method mentioned in the datasheet. According to which, the IRQ pin should be active low whenever Rx or Tx pins are active, and an Interrupt should be generated.
But the IRQ pin remains high nonetheless. I have set up an external 1k ohm pull-up resistor as mentioned with 3.3v VDD.
My goal is to use vk16e gps module through spi pins on an arduino uno. I have set up the low interrupt on digital pin 2 and it is working fine. If I manually connect this pin to the ground, the gps data appears successfully. But not with the IRQ pin.
I had a similar issue. Finally I found out that the interrupt pin on the breakout board is not connected to the 2kOhm IRQ pull up.
I added a white wire and now it works fine.

Resources