• How to use the ST-LINK/V2-1 in STM32L476G-DISCO Board to program the STM32 on an external application board

    Here is the video showing all the steps.

    ST-Link V2-1 on STM32L476G-Disco Board

    To use the ST-LINK/V2-1 to program the STM32 on an external application board (out of the STM32L476VGT6 onboard), remove the two jumpers from CN3 as shown in the above figure in red, and connect the board to the CN4 software debug connector according to Table.
    Make sure the jumpers JP6.3V3, and JP5.OFF are set.
    JP3, must be ON if CN4 pin 5 (NRST) is used in the external application board.

    PinCN4 FunctionJTAG PIN NumberJTAG NameNote
    1VappVDD from ApplicationDo not Connect Vapp to JTAG.
    2SWCLKSWD Clock9TCK
    3GNDGround1 to 9GND
    4SWDIOSWD data input/output7TMS
    5NRSTRESET of target MCU15nSRST
    6SWORESERVED

    Note: Do not connect Vapp to JTAG on the external board unless you know about the power domain of the external board.
    Power the board separately.

    You can use STM32CubeProgrammer to read the memory and also write the hex file into the microcontroller.

    Here I am using mini stm32 v3.0 as an example.

    The mini stm32 v3.0 has an STM32F103RB microcontroller along with a JTAG interface for programming and debugging.

  • How to make ATmega GPIO work as Input or Output

    AVR Input Output Port programming means you have to program its GPIO pins.

    GPIO – General Purpose Input and Output

    The GPIO is a very important peripheral of the microcontroller. Using the GPIO we can use the same exact pin for Input or Output.

    To make the PIN input or output we need to set a bit in the data direction register DDR

    Now lets take the example of ATmega16. Atmega 16 has 4 ports.
    -PORT A
    -PORT B
    -PORT C
    -PORT D

    Each PORT has 8 pin
    Each pin can be addressed individually
    PortA.1 = Pin 1 of Port A
    PA.1 = Pin 1 of Port A

    To make a PIN input/output
    DDRx = 1 // make the pin output
    DDRx = 0 // make the pin input

    Here x is to be replaced by port number
    DDRA = DDR for port A


    To Set the value of the pin we use
    PORTx = 1 // set all the pins of the port to HIGH
    PORTx = 0// Set all the pins of the port to LOW

    To Read the value of the pin we use
    PINx
    usage:
    int read_in;
    DDRx = 0;
    PORTx = 1; // This will enable the internal Pull up
    read_in = PINx; // read_in variable will store the value in PINx

    If the internal pull-up is not enabled than then value of the pin will always be in a floating state and it will not tell the accurate result.
    When the internal pull-up is not enabled then the external pull has to be enabled by the user.

  • Microcontroller + FPGA

    The microcontroller performs the task of minimization of peripherals on the PCB by miniaturization and integrating them in one housing.

    FPGA on the other hand is used to implement digital logic. Since FPGA can be programmed in a remote location using standard tools. And the growing market of the FPGA has made the tools required to program and debug very affordable.

    There are microcontrollers that have FPGA built inside of them. They can implement very small digital logic. But that will result in the minimization of components on the PCB.

    They bridge the gap between a dedicated FPGA and a microcontroller. For small applications which only needs a very small custom logic design, they can be used.

    Programmable System-On-Chip (PSoC) from Cypress semiconductor and C2000 TMS320F28379D from Texas Instrument are such examples.

    The FPGA can be used to implement the Finite State machines Logic.

    The microcontroller manufacturer also provides additional peripheral which can be connected in a customized fashion using the crossbar interconnects to make a custom peripheral. And since the logic is not outside there is high security.

    FPGA provided on these microcontrollers cannot replace the traditional FPGA.

    PSoC from Cypress is highly configurable and along with digital logic, it also has analogue peripheral such as op-amps and comparator which can be used to create custom logic.

  • PAL video signal

    PAL Video Signal

    Pal video signal consists of 625 individual lines.
    In 1 second we have 25 frames. Each frame is made from 625 horizontal lines.

    each line is 64 microseconds long.

    Out of the 625 horizontal lines, few lines are used for vertical synchronization.

    Each Horizontal line consist of
    -Horizontal Sync Start
    – Black Level
    – Color Burst (this can be ignored if you are using Black and white Signal)
    – Video Signal
    -Horizontal Sync End

    Vertical Sync lines consist of a transition section. In older analogue based Television this transition is used by the analogue system to shift the position of the electron gun from the bottom to the top of the screen.

    Vertical Syncline is made up of 32-microsecond periods. A total of 10 periods mark the transition of vertical sync.

  • Analog Modulation based Transmitter using ATmega16a

    Analog Modulation is the very basic form of modulation that can be produced using very basic components.

    The ATmega16a is used to generate a square wave. The frequency can be generated by carefully adjusting the 8-bit PWM Timer.

    Using the above method a Carrier Signal is generated.

    You can hear the carrier pulses on AM Radio. The reception is full of noise and interference.

    The range of such signals is not good. Since the EM wave has very low power.

    The circuit is given below.

    AM transmitter using ATmega16a

    AM Transmitter circuit

    /*
     * AM Transmitter.c
     *
     * Created: 11/10/2021 9:59:04 PM
     * Author : abhay
     */ 
    #define F_CPU 16000000
    #include <avr/io.h>
    #include <util/delay.h>
    
    
    void delay1(){
    	_delay_ms(20);
    }
    
    int main ()
    {
    	
    	TCCR0 = (1 << WGM01) | (1 << COM00) | (1 << CS00);
    		DDRB|=(1<<PB3);  /*set OC0 pin as output*/
    	
    	while (1)
    	{
    		OCR0 = 4;	// 1600 KHz
    		
    		delay1();    //This delay will create pulse of carrier frequency
    
    		OCR0 = 12;	//  615 kHz
    
    		delay1();    //This delay will create pulse of carrier frequency
    
    
    
    	}
    }

    PWM signal is being produced by an 8bit timer of the microcontroller.

    The formula used for the value of OCR0

    Where

    f clk_I/O = 16000000

    N = 1

    OCRn = (1,2,3 … 255)

    Frequency calculated using the formula

    The Antenna Used for AM Transmission in this setup is of very small length. Its range and quality get improved if you touch the antenna with your bare hands.

  • Up Counting Timer using STM32L476

    I have created this Upcounting timer using the RTC of STM32L476vgt. In this timer, time will keep on incrementing and it will be displayed using the onboard LCD.

    How to Read RTC of STM32L476G-DISCO

    Here is the code that I have used to make this.

    I have used STM32 CUBE IDE for programming and debugging purposes.

      MX_RTC_Init();				// RTC initalization and configuration created using integrated cube mx
      /* USER CODE BEGIN 2 */
      BSP_LCD_GLASS_Init();
      BSP_LCD_GLASS_Clear();
      BSP_LCD_GLASS_DisplayString((uint8_t *)"HALLO");
      HAL_Delay(1000);
      BSP_LCD_GLASS_DisplayString((uint8_t *)"EXASUB");
      HAL_Delay(2000);
    
    
      /* USER CODE END 2 */
    
      /* Infinite loop */
      /* USER CODE BEGIN WHILE */
    
      RTC_TimeTypeDef readTime;	// RTC Time structure
      RTC_DateTypeDef readDate;	// RTC Date structure
      while (1)
      {
        /* USER CODE END WHILE */
        MX_USB_HOST_Process();
    
        /* USER CODE BEGIN 3 */
    
        char bufSec[2];
        char bufMin[2];
        char bufHou[2];
        HAL_RTC_GetTime(&hrtc, &readTime, RTC_FORMAT_BIN);	// function to read time from RTC shadow register
        HAL_RTC_GetDate(&hrtc, &readDate, RTC_FORMAT_BIN);	// function to read date from RTC shadow register
       itoa(readTime.Seconds,bufSec,10);
       itoa(readTime.Minutes,bufMin,10);
       itoa(readTime.Hours,bufHou,10);
       if(readTime.Seconds == 0){
    	   BSP_LCD_GLASS_Clear();
       }
       if(readTime.Minutes == 0){
    	   BSP_LCD_GLASS_Clear();
       }
       /*
        if(readTime.Hours == 0){
       	   BSP_LCD_GLASS_Clear();
          }
       */
       BSP_LCD_GLASS_DisplayChar((uint8_t *)&bufHou[0], POINT_OFF, DOUBLEPOINT_OFF, 0);
       BSP_LCD_GLASS_DisplayChar((uint8_t *)&bufHou[1], POINT_OFF, DOUBLEPOINT_ON, 1);
       BSP_LCD_GLASS_DisplayChar((uint8_t *)&bufMin[0], POINT_OFF, DOUBLEPOINT_OFF, 2);
       BSP_LCD_GLASS_DisplayChar((uint8_t *)&bufMin[1], POINT_OFF, DOUBLEPOINT_ON, 3);
       BSP_LCD_GLASS_DisplayChar((uint8_t *)&bufSec[0], POINT_OFF, DOUBLEPOINT_OFF, 4);
       BSP_LCD_GLASS_DisplayChar((uint8_t *)&bufSec[1], POINT_OFF, DOUBLEPOINT_OFF, 5);
    
        HAL_Delay(1000);									// HAL Delay of 1000 millisecond
      }
      /* USER CODE END 3 */
    }

  • How to Read RTC of STM32L476G-DISCO

    Create a Project in STM32 CUBE IDE for the STM32L476G-DISCO board.

    Select LSE as Clock Source for RTC

    The default option is LSI which uses an internal RC circuit.

    LSE is the external 32KHz crystal that is provided on the board for the RTC.

    Activate the Clock source and Calendar

    This will enable the RTC clock source and will also enable the calendar for date and timekeeping.

    If you want to set some default time and date you can set it in the RTC configuration menu. You can always change them later through your code.

    After doing the above-said steps you can now generate code. This will give you an initialization code.

    To read the value from the RTC registers. You need to remember the following thing.

    From Section 38.3.8 of RM0351 Rev 1 Reference Manual

    It says that reading the sub-second register or Time register alone will lock the value. It will remain locked until the Date register is read.

    To prevent the lockup from happening. It is suggested to read time and date simultaneously one after the another.

    Here I am writing working code

     MX_RTC_Init();				// RTC initalization and configuration created using integrated cube mx 
      /* USER CODE BEGIN 2 */
    
      /* USER CODE END 2 */
    
      /* Infinite loop */
      /* USER CODE BEGIN WHILE */
    
      RTC_TimeTypeDef readTime;	// RTC Time structure 
      RTC_DateTypeDef readDate;	// RTC Date structure
      while (1)
      {
        /* USER CODE END WHILE */
        
    
        /* USER CODE BEGIN 3 */
    /*  function to read time from RTC shadow register */
        HAL_RTC_GetTime(&hrtc, &readTime, RTC_FORMAT_BIN);
    
    /* function to read date from RTC shadow register	*/
        HAL_RTC_GetDate(&hrtc, &readDate, RTC_FORMAT_BIN);
    
        printf("Minute: %d\t",readTime.Minutes);
        printf("Seconds: %d\n",readTime.Seconds);
    
        HAL_Delay(1000);	// HAL Delay of 1000 millisecond
      }
      /* USER CODE END 3 */
    }

    I am using print statements for debugging using stm32cube ide.
    How to use printf using serial wire debug on STM32L476 Discovery

  • IEEE 754 Double Precision Floating Point Format

    It is a 64-bit format for storing floating-point numbers.

    Bias = 1023

    It is also known as binary64 according to IEEE 754 standard given in 2008.

  • Memory Space in ATmega16A

    To effectively program AVR based microcontroller you must have knowledge about its memory space. Since there is not just one memory space. There are three different address spaces. They are:

    1. Data memory (SRAM)
      Here all your the intermediate results are stored and all the run time calculation get carried in this memory space.
    2. Program memory
      It is the memory where your application code is stored. And also it stores the constants. It could be divided into two sections by setting appropriate fuse bits. The two section will be:
      1. Application Section
      2. Boot Section
    3. EEPROM
      This is the memory where you can save the run time data such as configuration options, intermediate result for future processing. But it is very limited in size. So proper managment had to be taken care. Since it limits the size of certain applications.

    Out of the three memories present in the ATmega16a, only the SRAM is volatile.

    Size and address of memory space

    1. Data Memory
      1024 Bytes (Starting Address: 0x0060 – Last Address: 0x045F)
      96 Address which contain two section General purpose Register and I/O Registers.
      General Purpose Register ( Starting Address: 0x0000 – Last address: 0x001F)
      I/O register (Starting Address: 0x0020 – Last address: 0x005F)
    2. Program Memory
      Flash Type memory organised into 8000 memory location each pointing to a 16 bit wide data.
      Starting Address: 0x0000
      Last Address: 0x1FFF

    NOTE: Care must be taken while Read/Write operations of EEPROM. It is very sensitive to operating conditions. Variations outside the tolerance limits could result in corruption of data in the worst case total loss of stored data. It is highly recommended that a stable power source must be used if performing frequent EEPROM operations.