Hi, and welcome to our repo. This repo is prepared for educational purposes. I hope it will be useful and give you an opportunity to learn something and improve yourself. So let's Start!!!!!!!
Big thanks to Büşra Ülker @busraulker for their contributions to this repository
You can read this also from the pdf for readme.pdf !!! (The pdf is auto generated so sorry if some parts look bad)
Figure 1:Stm32g031k8 nucleo board pinout
As shown at Figure1, the pins can used for multiple purposes. The only digital pins are labeled with Dx and pins that can read analog signals with ADC is labeled with Ax.
Figure 2: Stm32g031k8 nucleo board back
The board include a usb port, this port allows code running and debugging using ST- link. For ST-link a stm32f103 IC is used and is connected to the back of the nucelo board. The stm32g0 IC operate at 3.3V because of it a 5V 3.3V regulator appear on the board. A 16Mhz oscillator appear to clock the stm32g0.
GPIOs (general-purpose input/output) port handles both incoming and outgoing digital signals. As an input port, it can be used to communicate to the CPU the ON/OFF signals received from switches, or the digital readings received from sensors.
Figure 3: GPIO structure
SRAM (static RAM) is a type of random-access memory (RAM) that retains data bits in its memory if power is being supplied. Unlike dynamic RAM (DRAM), which must be continuously refreshed, SRAM does not have this requirement, resulting in better performance and lower power usage.
The STM32G0 embeds up to 128 Kbytes of single-bank Flash memory. The Flash memory interface manages all memory access (read, programming and erasing) as well as memory protection, security and option bytes.
The direct memory access (DMA) controller is a bus master and system peripheral with single-AHB architecture. With 5 channels, it performs data transfers between memory-mapped peripherals and/or memories, to offload the CPU.
The DMAMUX request multiplexer enables routing DMA request lines from the peripherals to the DMA controllers in the products.
The CRC (cyclic redundancy check) calculation unit is used to get a CRC code using a configurable generator polynomial value and size, perform data integrity checks of off-/on-chip memories as a background task without CPU intervention.
Provides random numbers which are used when producing an unpredictable result is desirable.
The RCC peripheral is used to control the internal peripherals, as well as the reset signals and clock distribution. The RCC gets several internal (LSI, HSI and CSI) and external (LSE and HSE) clocks. They are used as clock sources for the hardware blocks, either directly or indirectly
The USART is a hardware that enables the device to communicate using serial protocol.
The analog-to-digital converters allows the microcontroller to accept an analog value like a sensor output and convert the signal into the digital domain
Provides. simple communication interface allowing the microcontroller. to communicate with external devices.
TIM peripheral is a multi-channel timer unit. It’s include advanced-control timers, general-purpose timers and basic timers.
The I2C is a multi-master, multi-slave, synchronous, bidirectional, half-duplex serial communication bus.
RTC, is a digital clock with a primary function to keep accurate track of time even when a power supply is turned off or a device is placed in low power mode.
PLL is a clock generation engine in the MCU which is used to generate the clock speed which is much higher than the internal HSI or external clock
The register shown in Figure 1 is defined as RCC_IOPENR, reset and clock setting is activated by making the related bits 1.
Figure 4: RCC_IOPENR register.
GPIOX base addresses were defined as GPIOX_BASE and these addresses were accessed to the registers that make the settings on the X ports. It is seen that there is an offsett of 0x400 between the ports.
Figure 5: GPIOX address map.
Using GPIOX_BASE addresses, the modes of the pins in the MODER registry can be set by accessing the MODER registry with offset 0x00.
Figure 6: GPIOx_MODER Register
Using GPIOX_BASE addresses, the ODR register is accessed with 0x14 Offset and the pins are powered by assigning a value of 1 to the relevant bits in the ODR register.
Figure 7: GPIOx_ODR register
Using GPIOX_BASE addresses, the IDR register is accessed with 0x10 Offset and the pins state can read by read this register.
Figure 8: GPIOx_IDR register
To turn on the LED connected to the PA8 pin, the clock of the GPIOA was first activated by set GPIOAEN bit (bit 0) in RCC_IOPENR register. Then, bits 12-13 were set to 01 in MODER for PA8 to be output. Finally, the LED was powered by setting OD8 to 1 in ODR.
Figure 9: Led on at PA8 pin.
This project includes a multi usage assembly gpio functions. You can take a look to improve yourself and it can be used later.
To turn on the LED connected to the PA11, PA12, PB4, PB5 pin, the clock setting of GPIOA and GPIOB was first activated. Then, MODE Pin values were set to 01 in MODER to make the pins output. Finally, the relevant pins in ODR were set to 1 and the LED was powered.
Figure 10: Four led on
In the beginning, the main function configures the microcontroller by enabling the clock for GPIOA (RCC_IOPENR register). To do this GPIOAEN is set to 1.
The pin PA8 is set to output mode by using GPIOA_MODER register. To do this the Mode 8 bits is set to 01.
Following the configuration, the blink_loop is initiated.This loop toggles the state of the LED on pin PA8 by reading the current state from the Output Data Register (GPIOA_ODR), XORing it with a mask that represents the state of the LED and storing the result back to the ODR. This effectively toggles the LED. The mask is 0x100, it makes only the bit 8 (OD8 bit) toggle and don’t effect to other bits.
After toggling the LED state, the program introduces a delay by executing a simple countdown loop (delay_loop). The DELAY_FREQ constant determines the duration of the delay, adjusting the speed of the LED blinking.** DELAY_FREQ **is loaded to r0 and subtract one with ***subs ***instruction, reference to Cortex-M0 Technical Reference Manual (figure 10) it will take one cycle than with bne instruction if r0 not equal to 0 they will go again to the countdown loop (delay_loop), reference to Cortex-M0 Technical Reference Manual it will take three cycle . The loop continues until the countdown reaches zero. Then go again to blink_loop label and toggle the led. So the delay_loop function execution time is 4 cycle (1 from subs, and 3 from ben). Assume the Clock is 16Mhz so 16M cycle appear in 1 second, so for waiting for 1 second we have to do a process of 16M cycle, for do this we made the loop count for 4M times, that’s make 16M cycle. The code with DELAY_FREQ = 4Mhz was tried, and a clock was kept, the result of the observation was that the LED was delayed by less than 1 second, faster than expected. Therefore, dividing the frequency by 3 was tried and the code was run. When done this way, it was observed that the delay was 1 second. Although we cannot fully explain the reason for this, it seems that it may be because the loop execution time is just 3 cycles.
Figure 11: Time of instructions Cortex-M0 Technical Reference Manual
The onboard led is connected to PC6 pin. The led is blinking by set the pin high and low with 1s intervals.
Figure 12: flowchart of ASSEMBLY_006_onbordled_blink
A button is connected to PA0 pin with pull down mode. When the button is pressed, the input PA0 pin becomes 1 and the LED connected to the PC6 pin on the board lights up. When the button is not pressed, the PA0 pin becomes 0 and the LED connected to the PC6 pin on the board does not light.
Figure 13: Schematic of ASSEMBLY_007_onboardled_on_with_button
Figure 14: Flowchart of ASSEMBLY_007_onboardled_on_with_button
The 8 pins of the B port were set to output mode and connected to the LEDs. LEDs were switched on and off with 1 second intervals.
Figure 15: Schematic of ASSEMBLY_008_8led_blink
Figure 16: Flowchart of ASSEMBLY_008_8led_blink
A button is connected to PA8 with pull down mode and the leds is connected to port B starting from PB0 to PB7. First starting from LED0, LED3 was switched on with 100 ms intervals. Then a shift pattern is set 0000 0111 for 8 bit as initial condition, 1 for leds on and 0 for off. Because registers are 32 bit we will do the pattern as 0000 0111 0000 0111 0000 0111 0000 0111.Than using rotate instruction, the shifting pattern is implemented. When the button pressed the shifting pattern change.
Figure 17: Schematic of ASSEMBLY_009_led_rotate
Figure 18: Flowchart of ASSEMBLY_009_led_rotate
Leds was connected to the pins of port B. Firstly, starting from LED0, LED3 was switched on with 100ms intervals. Then the led numbers were shifted to the right with 100ms intervals. With the algorithm created, when LED8 was reached, it was shifted towards LED0, and when LED0 was reached, it was shifted towards LED8.
Figure 19: Schematic of ASSEMBLY_010_knight_rider
Figure 20: Flowchart of ASSEMBLY_010_knight_rider
As a software method we can record SysTick values before and after delay. Hence the difference between these values can be calculated. An oscilloscope can be used as a hardware method. Calculating the time difference between the toggled signal frequency at the start and end of the delay. -oscilloscope used for measure the frequencies-
Figure 21: Flowchart of REGC_001_ledblink_systick
I cant find it in the stm32g0 referance manuel or datacheet so i tahe these photoes from stm32f4 datasheet.
Figure 22: Reload register
Figure 23: Current value register
Figure 24: Systick Control and Status Register
The TIM2 timer interrupt is used to change the state of the LED by tracking the time. The EXTI interrupt is used to increase or decrease the blinking rate of the LED when a button is pressed. As a result, it realizes an application that uses timer and external interrupts to control the LED to blink at a specific speed.
Figure 25: Flowchart of REGC_002_timer_interrupt
Figure 26: Schematic of REGC_002_timer_interrupt
Figure 27: Control register 1 of TIMx
This register is used in the code to enablle or disable timer.To understand the usage you can take a look to Start_TIM2(void) function.
Figure 28: TIMx Prescaler register
Figure 28: TIMx Counter register (CNT)
Figure 29: TIMx auto reload register
Figure 29: TIMx Interrupt enable register (DIER)
It is used to update interrupt enable.
Figure 30: Extenal interrupt control register (EXTICR)
- EXTICR (External Interrupt Configuration Register) : This register is used to select the GPIO port that is connected to the EXTI line. The STM32 microcontrollers have multiple EXTICR registers (EXTICR1, EXTICR2, etc.), each controlling a group of EXTI lines.
EXTI_EXTICR1_EXTI0_0
: This specific bit setting in theEXTICR[1]
register connects EXTI line 0 to GPIO port A. The notation[1]
seems to be a mistake here since EXTI0 configuration should be inEXTICR[0]
(assuming EXTICR registers are zero-indexed in your environment). The correct approach to connect EXTI1 to GPIOA Pin 0 would typically involveEXTICR[0]
and setting the appropriate bits for GPIOA.
Figure 31: Extenal interrupt rising trigger selection register (EXTI_RTSR1)
- RTSR1 (Rising Trigger Selection Register 1) : This register is used to enable rising edge triggers on the EXTI lines. Setting a bit in this register selects the corresponding EXTI line to be sensitive to rising edges.
EXTI_RTSR1_RT0
: Setting this bit enables EXTI line 0 to trigger an interrupt request on a rising edge.
Figure 32: Extenal interrupt falling trigger selection register (EXTI_FTSR1)
- FTSR1 (Falling Trigger Selection Register 1) : Similar to RTSR1, but for falling edge triggers.
EXTI_FTSR1_FT0
: Clearing this bit (&= ~EXTI_FTSR1_FT0
) ensures that EXTI line 0 will not trigger an interrupt request on a falling edge, making it sensitive to rising edges onlyEXTI->IMR1- IMR1 (Interrupt Mask Register 1) : This register is used to enable or disable interrupt requests from the EXTI lines.
EXTI_IMR1_IM0
: Setting this bit enables interrupt requests from EXTI line 0. This means that when the selected edge (rising, in this case) is detected on EXTI line 0, an interrupt request will be generated.
- PSC (Prescaler Register) : This register determines the division factor applied to the timer's clock. By slowing down the clock, the timer can count at a slower rate, allowing for longer intervals.
- CNT (Counter Register) : Acts as the core of the timer, incrementing on each clock cycle. When it reaches the value in the ARR, an event can be triggered.
- ARR (Auto-Reload Register) : Specifies the value to which the CNT register resets after reaching its maximum count. This defines the period of the timer's cycle.
The frequency of the timer can be calculated using the formula:
Frequency = Clock / ((PSC + 1) * (ARR ))
.
Adjusting the PSC and ARR values allows for fine-tuning of the timer's frequency for various applications.
The clock i 16 Mhz for this application.
In this problem, pushbutton control was provided on the seven segment display using external interrupts. When the button is pressed, the led on and the display starts to increase starting from 0, when it reaches 999, it stops and the led off. If the button is pressed again during the process, the display will reset and start over.
Figure 33: Flowchart of REGC_003_seven_segment
Figure 34: Schematic of REGC_003_seven_segment
For the independent watchdog timer, the time is set according to the following parameters and the blinking of the led is tested. If the set time is exceeded and the watchdog is not refreshed, the system will be reset.
Figure 35: IWDG key Register (IWDG_KR)
Figure 36: IWDG Prescaler Register (IWDG_PR)
Figure 37: IWDG Reload Register (IWDG_RLR)
Figure 38: time calculation
Figure 39: flowchart of REGC_004_ledblink_watchdog
The system was tested by adding watchdog timer while working as in REGC_003_seven_segment . If the watchdog timer time is made 16 s and watchdog refresh is not done within this time, the screen is reset and starts counting from the beginning.
Figure 40: flowchart of REGC_005_seven_segment_with_watchdog
Figure 41: Schematic of REGC_005_seven_segment_with_watchdog
The aim of this project is creating the functions of transmitting and receiving data.
When we observe the code, first GPIOA, USART2 module clocks and PA2, PA3 pins are enabled from RCC. Then PA2 and PA3 pins settled as alternate function for the USART2 module. CR1 control register choose from datasheet at enabling receive and transmit from USART2 module. TDR and RDR registers used at data transmit and receive processes respectively. Baud rate settled to 9600 bps assuming clock is running at 16Mhz. Value chosen according to the formula of baud rate and EISA RS-232 communication Standard.
Baud Rate = APBxCLK / USARTx
Some of the standard baud rates: 300, 600,
1200, 2400, 4800, 9600, 14400, 19200, 38400, 57600, 115200, 230400, 460800.
Figure 42: Flowchart of REGC_006_uart
Pulse Width Modulation is a technique used to encode information in the duration of a pulse signal. By changing the duty cycle of the PWM signal LED brightness can be changed.
Figure 43: Duty cycle led brightness relationship
PWM involves rapidly toggling a digital signal between high and low states. The frequency of the PWM signal can calculated by the above formula:
Figure 44: PWM frequency formula
To set the PWM frequency to 1 Khz, because the clock is default 16Mhz, PSC register value is set as 15, and ARR register value as 1000. To set the duty cycle the CCR register value can changed. The duty cycle percentage can be calculated by the above formula:
Figure 44: PWM Duty cycle formula
So as an example, to set duty cycle to 40% CCR value must be equal to 400.
TIM2 is used to generate the PWM signal, and the interrupt is activated. In the interrupt the duty cycle of the PWM signal is updated. By using the Systick timer a counter is increased and decreased. The counter is set as PWM duty cycle in the TIM2 interrupt. So, every 1ms the counter increase by 1, this is equal to 0.1% of duty cycle.
Figure 45: Flowchart of REGC_007_pwm
Figure 46: Schematic of REGC_007_pwm
The columns of the keypad were set as output and rows as input. Columns were connected to EXTI and keypad keys were controlled. First the column was determined from the incoming interrupt, then the rows were controlled and the key pressed was determined. Significant numbers entered were stored until "# came. Significant values between 0 and 100 affected the duty cycle, while other meaningless values and signs gave a warning. PWM was controlled with TIM2, UART was controlled with TIM3.
Figure 47 : Duty cycle of pwm signal
The internal structure of 4X4 KEYPAD MODULE is shown below.
Figure 48 : Keypad circuit model
Figure 49 : Flowchart of REGC_008_withkeypad
Figure 50: Schematic of REGC_008_withkeypad
The STM32G0 microcontroller reads analog
signal with ADC from the pot connected to pin PA12, converts the ADC values to voltage, and set the duty cycles of the 2 PWM channels according to the ADC value. Each led is connected to PWM channel at pins PA15 and PB3. When the pot is turned to the left the ADC value will be 0 and the left led will bright with a full brightness (full duty cycle) when turning to the right the brightness of the left led decrease. At the middle the left led turn off, then when turning to the right the right led will turn on from low to high brightness according to the PWM signal duty cycle.
Figure 51 : Flowchart of REGC_009_ADC_POT_PWM_led_control
Figure 52 : Schematic of REGC_009_ADC_POT_PWM_led_control
In this problem, the sound sensor and the IMU sensor is combined to detect knock and write the number of the knocks to the seven-segment display. The IMU sensor data, acceleration and gyro for each axis is read using I2C protocol. The gyro is measuring the angle velocity from 0 to 250 degree per second. Always the sensor is read, and smooth data is obtained by using exponential smoothing, by a factor of 0.001. When the instant value of the gyro in one of any axes is far then the smooth gyro data 20 degree/second, it’s mean that a vibration detected and it’s that the IMU say that is a possible knock. Then the sound data is read from sound sensor if a high sound detected that is a possible knock. If at the same time the IMU sensor and the sound sensor detect a possible knock that’s mean that’s really knock and the knock counter increase. Then the timer flag is set to zero and timer 3 counter set to 0. After 100ms the timer flag will set to 1 inside the interrupt. The knock check will only be done if the flag value is 1. This method avoid blocking delay and the debouncing of knock checking.
To make this project REGC_010_sound_sensor_ADC and REGC_011_mpu6050 is used.
Figure 53 : Flowchart of REGC_012_knock_detector
Figure 54 : Schematic of REGC_012_knock_detector