I'm using an ATmega4808 32 Pin. I have 2 LEDs connected to the pins PA0 and PA1. I want to set both high. Unfortunatly only the PA1 LED is on.
I figured out the PA0 Pin could be set to EXTCLK by default. If this is the problem i can't find the solution to change the port to GPIO.
int main(int argc, char** argv) {
PORTA.DIRSET = PIN0_bm; // Config PA0 as output
PORTA.DIRSET = PIN1_bm; // Config PA1 as output
PORTA.OUTSET = PIN0_bm; // Set Pin PA0 to HIGH
PORTA.OUTSET = PIN1_bm; // Set Pin PA1 to HIGH
while(1){
}
return (EXIT_SUCCESS);
}
The configuration of PIN0 is lost by writing again to registers PORTA.DIRSET and PORTA.OUTSET.
Try using | (bitwise OR) to not discard PIN0 config:
PORTA.DIRSET = PIN0_bm; // Config PA0 as output
PORTA.DIRSET |= PIN1_bm; // Config PA1 as output
PORTA.OUTSET = PIN0_bm; // Set Pin PA0 to HIGH
PORTA.OUTSET |= PIN1_bm; // Set Pin PA1 to HIGH
Or, to set them at the same time:
PORTA.DIRSET = PIN0_bm | PIN1_bm; // Config PA0 and PA1 as output
PORTA.OUTSET = PIN0_bm | PIN1_bm; // Set Pin PA0 and PA1 to HIGH
Related
I'm a beginner when it comes to using STM chips, and I have a project where I have to use all three USART terminals in Uvision.
I am using an STM32F103RB chip, and I already got the first two USART_init functions working, but I can't get the third one to work for some reason. I would really appreciate any help
Here are my USART_init functions:
/*----------------------------------------------------------------------------
Initialize UART pins, Baudrate
*----------------------------------------------------------------------------*/
void USART1_Init (void) {
int i;
RCC->APB2ENR |= ( 1UL << 0); /* enable clock Alternate Function */
AFIO->MAPR &= ~( 1UL << 2); /* clear USART1 remap */
RCC->APB2ENR |= ( 1UL << 2); /* enable GPIOA clock */
GPIOA->CRH &= ~(0xFFUL << 4); /* clear PA9, PA10 */
GPIOA->CRH |= (0x0BUL << 4); /* USART1 Tx (PA9) output push-pull */
GPIOA->CRH |= (0x04UL << 8); /* USART1 Rx (PA10) input floating */
RCC->APB2ENR |= ( 1UL << 14); /* enable USART#1 clock */
USART1->BRR = 0x0271; /* 115200 baud # PCLK2 72MHz */
USART1->CR1 = (( 1UL << 2) | /* enable RX */
( 1UL << 3) | /* enable TX */
( 0UL << 12) ); /* 1 start bit, 8 data bits */
USART1->CR2 = 0x0000; /* 1 stop bit */
USART1->CR3 = 0x0000; /* no flow control */
for (i = 0; i < 0x1000; i++) __NOP(); /* avoid unwanted output */
USART1->CR1 |= (( 1UL << 13) ); /* enable USART */
}
/*----------------------------------------------------------------------------
Initialize UART2 pins, Baudrate
*----------------------------------------------------------------------------*/
void USART2_Init (void) {
RCC->APB2ENR |= 1; // enable clock for AF
AFIO->MAPR |= 1<<3; // set USART2 remap
RCC->APB2ENR |= 1<<5; // enable clock for GPIOD
GPIOD->CRL &= ~(0xFF << 20); // Clear PD5, PD6
GPIOD->CRL |= (0x0B << 20); // USART2 Tx (PD5) output push-pull
GPIOD->CRL |= (0x04 << 24); // USART2 Rx (PD6) input floating
RCC->APB1ENR |= 1<<17; // enable clock for USART2
USART2->BRR = 0x138; // set baudrate -115.2kB from 36MHz
USART2->CR1 &= ~(1<<12); // force 8 data bits
USART2->CR2 &= ~(3<<12); // force 1 stop bit
USART2->CR3 &= ~(3<<8); // force no flow control
USART2->CR1 &= ~(3<<9); // force no parity
USART2->CR1 |= 3<<2; // RX, TX enable
USART2->CR1 |= 1<<5; // Rx interrupts if required
NVIC->ISER[1] = (1 << 6); // enable interrupts if required
USART2->CR1 |= 1<<13; // USART enable
}
/*----------------------------------------------------------------------------
Initialize UART3 pins, Baudrate
*----------------------------------------------------------------------------*/
void USART3_Init (void) {
RCC->APB2ENR |= 1; // enable clock for AF
AFIO->MAPR |= 1<<3; // set USART3 remap
RCC->APB2ENR |= 1<<4; // enable clock for GPIOC
GPIOC->CRH &= ~(0xFFUL << 4); /* clear PC10, PC11 */
GPIOC->CRH |= (0x04UL << 8); /* USART3 Rx (PC10) input floating */
GPIOC->CRH |= (0x01UL << 8); /* USART3 Tx (PC11) output push-pull */
RCC->APB1ENR |= 1<<20; // enable clock for USART3
USART3->BRR = 0x138; // set baudrate -115.2kB from 36MHz; USART3
//should have the same baudrate as USART2
USART3->CR1 &= ~(1<<12); // force 8 data bits
USART3->CR2 &= ~(3<<12); // force 1 stop bit
USART3->CR3 &= ~(3<<8); // force no flow control
USART3->CR1 &= ~(3<<9); // force no parity
USART3->CR1 |= 3<<2; // RX, TX enable
USART3->CR1 |= 1<<5; // Rx interrupts if required
NVIC->ISER[1] = (1 << 6); // enable interrupts if required
USART3->CR1 |= 1<<13; // USART enable
}
Your first line for the USART3 initialization is wrong :-)
RCC->APB2ENR |= 1; // enable clock for AF
must be (without a clock the USART doesn't work)
RCC->APB1ENR |= (1<<18); // enable clock for USART
And as an additional hint, do not use all these magic numbers for the bits.
This is much more readable (and the needed defines are already done in the CMSIS:
RCC->APB1ENR |= RCC_APB1ENR_USART3EN; // enable clock for USART
After some research, I found there were more problems than just the clock not being enabled. Below is the complete code of the initialization for UART3 using an STM32F103RB chip
/*----------------------------------------------------------------------------
Initialize UART3 pins, Baudrate
*----------------------------------------------------------------------------*/
void USART3_Init (void) {
RCC->APB2ENR |= 1; // enable clock for AF
AFIO->MAPR |= AFIO_MAPR_USART3_REMAP_PARTIALREMAP; // set USART3 to partical remap to use PC10 and PC11
RCC->APB2ENR |= 1<<4; // enable clock for GPIOC
// since our pins are above 8, we use H instead of L
// since we are using 10 & 11 we will be using bits 8-15 in the CRH register
/* USART3 Tx (PC10) output push-pull */
GPIOC->CRH &= ~(0xFFUL << 8);
GPIOC->CRH |= (0x0BUL << 8);
/* USART3 Rx (PC11) input floating */
GPIOC->CRH |= (0x04UL << 12);
RCC->APB1ENR |= RCC_APB1ENR_USART3EN; /* enable clock for USART3 */
USART3->BRR = 0x138; /* set baudrate -115.2kB from 36MHz */
USART3->CR1 = (( 1UL << 2) | /* enable RX */
( 1UL << 3) | /* enable TX */
( 0UL << 12) ); /* 1 start bit, 8 data bits */
USART3->CR2 = 0x0000; /* 1 stop bit */
USART3->CR3 = 0x0000; /* no flow control */
USART3->CR1 |= 1<<13; /* USART3 enable */
//Configure and enable USART3 interrupt
NVIC->ICPR[USART3_IRQn/32] = 1UL << (USART3_IRQn%32); // clear any previous pending interrupt flag
NVIC->IP[USART3_IRQn] = 0x80; // set priority to 0x80
NVIC->ISER[USART3_IRQn/32] = 1UL << (USART3_IRQn%32); // set interrupt enable bit
USART3->CR1 |= USART_CR1_RXNEIE; // enable USART3 receiver not empty interrupt
}
and the interrupt I used to prove this works looks like this
// UART3 Interupt Handler
void USART3_IRQHandler (void) {
uint8_t inKey3 = (int8_t) (USART3->DR & 0x1FF);
SendCharTo3(inKey3);
if(inKey3 == 0x0D) {
SendCharTo3('\n');
}
}
/*----------------------------------------------------------------------------
SendChar
Write character to Serial Port. for UART 3
*----------------------------------------------------------------------------*/
int SendCharTo3 (uint8_t ch) {
while (!(USART3->SR & USART_SR_TXE));
USART3->DR = ((uint16_t)ch & 0x1FF);
return (ch);
}
Hi Everyone and thank you for your time.
I have been working on interfacing the STM32f446RE Nucleo board with the TLV5628 8 Bit Octal Serial DAC. I have ran into multiple issues, but the current issue has been one of two things:
1) The data and clock lines showing the exact same information
or
2) The data line showing information, but nothing on the clock line.
Regardless, the information coming out is completely incorrect.
Here is my setup code:
void SPI_INIT(void){
// Enable clocks for C
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN;
// SPI GPIO
GPIOC->MODER |= 2 << 3*2; // PC3 data pin
GPIOC->MODER |= 2 << 7*2; // PC7 clock pin
GPIOC->MODER |= 1 << 2*2; //pc2 load
GPIOC->MODER |= 1 << 4*2; //pc4 ldac - probably set low permanently
// Pins default to push-pull
// set all to high speed
GPIOC->OSPEEDR |= (3 << 2*2) | (3 << 3*2) | (3 << 4*2) | (3 << 7*2);
GPIOC->AFR[0] |= 5<< 6*2; // Alt func 5 pc3 - SPI2
GPIOC->AFR[0] |= 5 << 7*2; // Alt func 5 pc7 - SPI2
// SPI Setup
RCC->APB1ENR |= RCC_APB1ENR_SPI2EN; // Enable SPI Clock
RCC->APB1RSTR |= RCC_APB1RSTR_SPI2RST; // reset SPI2
RCC->APB1RSTR &= ~RCC_APB1RSTR_SPI2RST;// clear the reset
// Control Register 1
SPI2->CR1 &= ~SPI_CR1_SPE; // Disable SPI
SPI2->CR1 |= SPI_CR1_MSTR; // master mode
SPI2->CR1 &= ~SPI_CR1_RXONLY; // transmit, 0 == full duplex
SPI2->CR1 &= ~SPI_CR1_DFF; // 8 bit format
SPI2->CR1 &= ~SPI_CR1_LSBFIRST; // MSB first
SPI2->CR1 &= ~SPI_CR1_CPOL;// low polarity, so 0 when idle
SPI2->CR1 |= 4 << 3; // (180M/4)/32 = 1.41 MHz
SPI2->CR1 |= SPI_CR1_CPHA; // first edge, look in data sheet
//Questionable settings
// Biderectional data line
SPI2->CR1 |= SPI_CR1_BIDIMODE; // 1/17/2019 --> Check to see if this fixes something
SPI2->CR1 |= SPI_CR1_BIDIOE; // idk if i need this
// CRC Polynomial Register
SPI2->CRCPR = 10;
// Control Register 2
SPI2->CR2 |= 1<<2; // SS output enabled
SPI2->CR1 |= SPI_CR1_SPE; // enable, has to be last
}
And here is my SPI Write code:
void SPI_Write(int dacSelect, int adcData){
while((SPI2->SR & SPI_SR_TXE) != 0);
GPIOC->ODR |= 1 << 2; // load set high to read data
SPI2->DR = dacArray[dacSelect]; // send address
SPI2->DR = adcData; // send adc data
while((SPI2->SR & SPI_SR_BSY) == SPI_SR_BSY);
GPIOC->ODR &= ~(1 << 2); // Send load low to load data
Delay(10); // short delay
GPIOC->ODR |= 1 << 2;
}
You can use STMCubeMX to generate codes for STM microprocessors and boards. Following code blocks are generated from STM32ubeMX for STM32F4. You should change baudrate for your sensor.
SPI_HandleTypeDef hspi;
SPI_HandleTypeDef SpiHandle;
void Spi_Initialize(void)
{
/*##-1- Configure the SPI peripheral #######################################*/
/* Set the SPI parameters */
SpiHandle.Instance = SPI2;
SpiHandle.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
SpiHandle.Init.Direction = SPI_DIRECTION_2LINES;
SpiHandle.Init.CLKPhase = SPI_PHASE_1EDGE;
SpiHandle.Init.CLKPolarity = SPI_POLARITY_LOW;
SpiHandle.Init.DataSize = SPI_DATASIZE_8BIT;
SpiHandle.Init.FirstBit = SPI_FIRSTBIT_MSB;
SpiHandle.Init.TIMode = SPI_TIMODE_DISABLE;
SpiHandle.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
SpiHandle.Init.CRCPolynomial = 7;
SpiHandle.Init.NSS = SPI_NSS_SOFT;
SpiHandle.Init.Mode = SPI_MODE_MASTER;
if(HAL_SPI_Init(&SpiHandle) != HAL_OK)
{
while(1){};
}
}
void Spi_Read(void )
{
uint8_t SpiData[2];
uint8_t tempmessage = 8;
HAL_GPIO_WritePin(GPIOG,GPIO_PIN_8,RESET); // CS pin
HAL_SPI_TransmitReceive(&hspi,&tempmessage,SpiData,2,5000); // Read Data
HAL_GPIO_WritePin(GPIOG,GPIO_PIN_8,SET); // CS Pin
}
void Spi_Write(uint8_t *Data, uint8_t size)
{
HAL_GPIO_WritePin(GPIOG,GPIO_PIN_8,RESET); // CS pin
HAL_SPI_Transmit(&hspi, Data, size, 5000); // Write Data
HAL_GPIO_WritePin(GPIOG,GPIO_PIN_8,SET); // CS Pin
}
I am looking to receive serial data from an arduino, and then transmit the data received back to the arduino, however I am having trouble receiving the correct data. Below is my code, I am not sure on where I have gone wrong, can anyone see any problems?
I am using register level programming and using USART 3 on the STM32L476RG development board, an I am using ADM485 chip to transfer the data between each serial port.
#include "stm32L476XX.h"
#include "stdio.h"
int T ;
int R ;
uint8_t z;
void USART3_init(void)
{
USART3->BRR |= 26UL<<4; //BAUD RATE MANTISSA 234UL<<4
USART3->BRR |= 1UL<<0; // BAUD RATE FRACTION 6UL<<0
USART3->CR1 |= 1UL<<0; //enable USART
USART3->CR1 ^= 0UL<<28; //1 start bit, 8 data bits, n stop bit
USART3->CR1 ^= 0UL<<12; //also sets word length to 8 data bits
USART3->CR1 ^= 0UL<<10; //no parity control
USART3->CR1 |= 1UL<<6; //Transmission complete interrupt enabled
USART3->CR1 |= 1UL<<7; //TXE interrupt enable
USART3->CR1 |= 1UL<<5; //RXNEIE interrupt enable
USART3->CR2 ^=00UL<<12; //1 stop bit
USART3->CR1 |= 1UL<<3; // enable transmitter
USART3->CR1 |= 1UL<<2; // enable receiver
NVIC_EnableIRQ(USART3_IRQn); //enable USART interrupts
}
void Delay(void)
{
uint32_t i=0;
for (i=0; i<50000; i++){}
}
void USART3_IRQHandler(void)
{
//Delay();
if ((USART3->ISR>>5)&1UL) //Check if RXNE interrupt is high
{
z = USART3->RDR; //put what is on RDR into Z (also clears RXNE flag)
GPIOB->ODR |= 1UL<<5; //set transceiver into transmit mode USART3->TDR = z; // Clears TXIE flag and outputs z on TX
}
if ((USART3->ISR>>7)&1UL) //Check if TXIE interrupt is high
{
GPIOB->ODR &= 0UL<<5; //sets transceiver in receive mode
}
if ((USART3->ISR>>6)&1UL) //Check if TC interrupt is high
{
USART3->ICR |= 1UL<<6; //Clear TC flag
GPIOB->ODR &= 0UL<<5; //Set transceiver in receive mode
}
}
void RCC_GPIO_init(void)
{
RCC->APB1ENR1 |= 1UL<<18; //Enable USART 3 clock
RCC->AHB2ENR |= 1UL<<1; //Enable GPIOB clock
GPIOB->MODER = 0; //reset all register bits
GPIOB->MODER |= 2UL<<20; //enable GPIOB pin 10 as alternate function
GPIOB->MODER |= 2UL<<22; //enable GPIOB pin 11 as alternate function
GPIOB->MODER |= 1UL<<10; //enable GPIOB pin 5 as output
GPIOB->AFR[1] = 0; //reset all register bits
GPIOB->AFR[1] |= 7UL<<8; //enable GPIOB pin 10 as TX
GPIOB->AFR[1] |= 7UL<<12; //enable GPIOB pin 10 as RX
GPIOB->ODR ^= 0UL<<5; //GPIOB pin 5 as low (to put ADM485 transceiver in receive mode)
}
int main (void)
{
RCC_GPIO_init();
USART3_init();
while(1)
{
}
}
It's actually a basic code for controlling buzzer with leds. I did with HAL libraries.But the institution I was working with wanted to do this at the register level too. But I couldn't it. It's not too complicated however i don't understand where the problem is.
My code in below.
#include "stm32f10x.h"
void SystemCoreClockConfigure(void)
{
RCC->CR |= ((uint32_t)RCC_CR_HSION); // Enable HSI
while ((RCC->CR & RCC_CR_HSIRDY) == 0); // Wait for HSI Ready
RCC->CFGR = RCC_CFGR_SW_HSI; // HSI is system clock
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI); // Wait for HSI used as system clock
FLASH->ACR = FLASH_ACR_PRFTBE; // Enable Prefetch Buffer
FLASH->ACR |= FLASH_ACR_LATENCY; // Flash 1 wait state
RCC->CFGR |= RCC_CFGR_HPRE_DIV1; // HCLK = SYSCLK
RCC->CFGR |= RCC_CFGR_PPRE1_DIV2; // APB1 = HCLK/2
RCC->CFGR |= RCC_CFGR_PPRE2_DIV1; // APB2 = HCLK
RCC->CR &= ~RCC_CR_PLLON; // Disable PLL
// PLL configuration: = HSI/2 * 12 = 48 MHz
RCC->CFGR &= ~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL);
RCC->CFGR |= (RCC_CFGR_PLLSRC_HSI_Div2 | RCC_CFGR_PLLMULL12);
RCC->CR |= RCC_CR_PLLON; // Enable PLL
while((RCC->CR & RCC_CR_PLLRDY) == 0) __NOP(); // Wait till PLL is ready
RCC->CFGR &= ~RCC_CFGR_SW; // Select PLL as system clock source
RCC->CFGR |= RCC_CFGR_SW_PLL;
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL); // Wait till PLL is system clock src
}
This is the first oscillator activation part.I know that there is no problem until the main function.
In main:
int main(void)
{
SystemCoreClockUpdate();
SysTick_Config(SystemCoreClock / 1000);
RCC->APB2ENR |= (1UL << 2); /* Enable GPIOA clock */
RCC->APB2ENR |= (1UL << 4); /* Enable GPIOC clock */
// Configure the GPIO Buttons
GPIOA->CRL = 0x00000044; //1SET // GPIOA -> 0,1
GPIOC->CRL = 0x00004400; //3SET // GPIOC -> 3,2
while (1)
{
if(GPIOA->IDR == 0x0000003) // PA1 ON (Led4) //
{
GPIOC->CRH = 0x00000002; // BUZZER SET
GPIOC->BSRR = 0x00000100; // BUZZER ON
}
}
}
I'm using keil and I know that if i only set and on buzzer after
GPIOC->CRL = 0x00004400; //3SET // GPIOC -> 3,2
it's working.But with the reading input to button with GPIO->IDR(Input Data Reg.) It's not toggle or whatever i don't know.I've been stuck here for a week and it's really annoying. Heelp me !?
the code inside your while loop is completely wrong!
while(1)
{
if((GPIOA->IDR & 0x02) == 0x02) // 0x02 = 0b10 = PA1 (LED4)
{
GPIOC->BSRR = 0x100; // ON
}
else
{
GPIOC->BSRR = (0x100 << 16); // OFF
}
}
and also set the GPIOC->CRH register only once before the while loop.
so basically I'm trying set up a ISR(Interrupt subroutine) to simply turn a light on, but the ISR doesn't seem to run. I've looked through the microcontroller datasheet a lot to see if I'm doing something wrong but I couldn't find anything.
Heres my code.
#include <asf.h>
int main (void) {
DDRD = 0b10000000;
cli(); // turn off global interrupts
//Timer
TCCR2A |=_BV(WGM21); //CTC mode
TCCR2B |=_BV(CS22)|_BV(CS21); //clk pre-scale 1/256
OCR2A = 0x7d; //125clk cycles = 2ms
TIMSK2 |=_BV(OCIE2A); //enable interrupt on compare matchA
TIFR2 |= _BV(OCF2A); //clear flag
TCNT2 = 0x00; // reset counter
sei(); // enable global interrupts
}
ISR(TIMER2_COMPA_vect) {
PORTD = 0b10000000;
}
You should have an endless loop at the end of your main() function:
#include <asf.h>
int main (void) {
DDRD = 0b10000000;
cli(); // turn off global interrupts
//Timer
TCCR2A |=_BV(WGM21); //CTC mode
TCCR2B |=_BV(CS22)|_BV(CS21); //clk pre-scale 1/256
OCR2A = 0x7d; //125clk cycles = 2ms
TIMSK2 |=_BV(OCIE2A); //enable interrupt on compare matchA
TIFR2 |= _BV(OCF2A); //clear flag
TCNT2 = 0x00; // reset counter
sei(); // enable global interrupts
while(1);
}
ISR(TIMER2_COMPA_vect) {
PORTD = 0b10000000;
}
Without endless loop your AVR reaches an undefined state!