Posted on Leave a comment

How to use AT24C32 EEPROM with ATmega328PB in Microchip Studio

AT24C32 is an i2c compatible serial EEPROM which can be programmed using a microcontroller.

The AT24C32 provides 32,768 bits of serial electrically erasable and programmable
read-only memory (EEPROM). The device’s cascadable feature allows up to 8 devices to share a common 2-
wire bus. The device is optimized for use in many industrial and commercial applications
where low power and low voltage operation are essential. The AT24C32/64 is
available in space-saving 8-pin JEDEC PDIP, 8-pin JEDEC SOIC, 8-pin EIAJ SOIC,
and 8-pin TSSOP (AT24C64) packages and is accessed via a 2-wire serial interface.
In addition, the entire family is available in 2.7V (2.7V to 5.5V) and 1.8V (1.8V to 5.5V)
versions.

/*
 * main.c
 *
 * Created: 8/24/2022 10:53:05 PM
 *  Author: abhay
 */ 
#define F_CPU 16000000
#include <xc.h>
#include "util/delay.h"
#include "uart.h"
#include <stdio.h>
#define FALSE 0
#define TRUE 1

void EEOpen();
uint8_t EEWriteByte(uint16_t,uint8_t);
uint8_t EEReadByte(uint16_t address);

int main(void)
{
	UART_Init();
	EEOpen();
	char buff[20];
	sprintf(buff,"Hello EEPROM TEST \nBy: \t ABHAY");
	UART_SendString(buff);
	//Fill whole eeprom 32KB (32768 bytes)
	//with number 7
	uint16_t address;
	char failed;
	failed = 0 ;
	for(address=0;address< (32768);address++)
	{
		sprintf(buff,"address =  %d \n",address);
		UART_SendString(buff);
		if(EEWriteByte(address,5)==0)
		{
			//Write Failed
			sprintf(buff,"write Failed %x \n",address);
			UART_SendString(buff);
			failed = 1;
			break;
		}
	}
	
	if(!failed)
	{
		//We have Done it !!!
		
		sprintf(buff,"Write Success !\n");
		UART_SendString(buff);
	}
    while(1)
    {
        //TODO:: Please write your application code 
		//Check if every location in EEPROM has
		//number 7 stored
		failed=0;
		for(address=0;address < 32768 ; address++)
		{
			if(EEReadByte(address)!=5)
			{
				//Failed !
			
				
				sprintf(buff,"Verify Failed %x \n",address);
				UART_SendString(buff);
				
				failed=1;
				break;
			}
		}

		if(!failed)
		{
			//We have Done it !!!
			
			sprintf(buff,"Write Success !\n");
			UART_SendString(buff);
		}
		
    }
}


void EEOpen()
{
	//Set up TWI Module
	TWBR0 = 5;
	TWSR0 &= (~((1<<TWPS1)|(1<<TWPS0)));

}

uint8_t EEWriteByte(uint16_t address,uint8_t data)
{
	do
	{
		//Put Start Condition on TWI Bus
		TWCR0=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN);

		//Poll Till Done
		while(!(TWCR0 & (1<<TWINT)));

		//Check status
		if((TWSR0 & 0xF8) != 0x08)
			return FALSE;

		//Now write SLA+W
		//EEPROM @ 00h
		TWDR0=0b10100000;	

		//Initiate Transfer
		TWCR0=(1<<TWINT)|(1<<TWEN);

		//Poll Till Done
		while(!(TWCR0 & (1<<TWINT)));
	
	}while((TWSR0 & 0xF8) != 0x18);
		

	//Now write ADDRH
	TWDR0=(address>>8);

	//Initiate Transfer
	TWCR0=(1<<TWINT)|(1<<TWEN);

	//Poll Till Done
	while(!(TWCR0 & (1<<TWINT)));

	//Check status
	if((TWSR0 & 0xF8) != 0x28)
		return FALSE;

	//Now write ADDRL
	TWDR0=(address);

	//Initiate Transfer
	TWCR0=(1<<TWINT)|(1<<TWEN);

	//Poll Till Done
	while(!(TWCR0 & (1<<TWINT)));

	//Check status
	if((TWSR0 & 0xF8) != 0x28)
		return FALSE;

	//Now write DATA
	TWDR0=(data);

	//Initiate Transfer
	TWCR0=(1<<TWINT)|(1<<TWEN);

	//Poll Till Done
	while(!(TWCR0 & (1<<TWINT)));

	//Check status
	if((TWSR0 & 0xF8) != 0x28)
		return FALSE;

	//Put Stop Condition on bus
	TWCR0=(1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
	
	//Wait for STOP to finish
	while(TWCR0 & (1<<TWSTO));

	//Wait untill Writing is complete
	_delay_ms(1);

	//Return TRUE
	return TRUE;

}

uint8_t EEReadByte(uint16_t address)
{
	uint8_t data;

	//Initiate a Dummy Write Sequence to start Random Read
	do
	{
		//Put Start Condition on TWI Bus
		TWCR0=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN);

		//Poll Till Done
		while(!(TWCR0 & (1<<TWINT)));

		//Check status
		if((TWSR0 & 0xF8) != 0x08)
			return FALSE;

		//Now write SLA+W
		//EEPROM @ 00h
		TWDR0=0b10100000;	

		//Initiate Transfer
		TWCR0=(1<<TWINT)|(1<<TWEN);

		//Poll Till Done
		while(!(TWCR0 & (1<<TWINT)));
	
	}while((TWSR0 & 0xF8) != 0x18);
		

	//Now write ADDRH
	TWDR0=(address>>8);

	//Initiate Transfer
	TWCR0=(1<<TWINT)|(1<<TWEN);

	//Poll Till Done
	while(!(TWCR0 & (1<<TWINT)));

	//Check status
	if((TWSR0 & 0xF8) != 0x28)
		return FALSE;

	//Now write ADDRL
	TWDR0=(address);

	//Initiate Transfer
	TWCR0=(1<<TWINT)|(1<<TWEN);

	//Poll Till Done
	while(!(TWCR0 & (1<<TWINT)));

	//Check status
	if((TWSR0 & 0xF8) != 0x28)
		return FALSE;

	//*************************DUMMY WRITE SEQUENCE END **********************


	
	//Put Start Condition on TWI Bus
	TWCR0=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN);

	//Poll Till Done
	while(!(TWCR0 & (1<<TWINT)));

	//Check status
	if((TWSR0 & 0xF8) != 0x10)
		return FALSE;

	//Now write SLA+R
	//EEPROM @ 00h
	TWDR0=0b10100001;	

	//Initiate Transfer
	TWCR0=(1<<TWINT)|(1<<TWEN);

	//Poll Till Done
	while(!(TWCR0 & (1<<TWINT)));

	//Check status
	if((TWSR0 & 0xF8) != 0x40)
		return FALSE;

	//Now enable Reception of data by clearing TWINT
	TWCR0=(1<<TWINT)|(1<<TWEN);

	//Wait till done
	while(!(TWCR0 & (1<<TWINT)));

	//Check status
	if((TWSR0 & 0xF8) != 0x58)
		return FALSE;

	//Read the data
	data=TWDR0;

	//Put Stop Condition on bus
	TWCR0=(1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
	
	//Wait for STOP to finish
	while(TWCR0 & (1<<TWSTO));

	//Return TRUE
	return data;
}

Posted on Leave a comment

How to use DS1307 RTC with ATmega328PB via I2C in Microchip Studio

The DS1307 Real Time Clock uses I2c communication lines to connect with the microcontroller.

I2C uses two lines commonly known as Serial Data/Address or SDA and Serial Clock Line or SCL. The two lines SDA and SCL are standardised and they are implemented using either an open collector or open drain configuration. What this means is that you need to pull these lines UP to VCC. For complete information on how the i2C is implemented in ATmega328PB, you need to go through the section of the datasheet called TWI or Two-Wire Serial Interface.

To start I2C in ATmega328PB, first the SCL frequency needs to set which must be under 100KHz .

To set the SCL frequency you set two registers TWBR0 and TWSR0.

TWSR0 has two bit 0 and bit 1; which sets the prescaler for the clock to the TWI.

Then TWBR0 needs to be set which can anything from 0 to 255.

THen you need to write the I2C functions for start, repeated start, data trasmission and recepetion and stop.

/*
 * main.c
 *
 * Created: 8/20/2022 2:08:09 PM
 *  Author: abhay
 */ 
#define F_CPU 16000000
#include <xc.h>
#include <avr/interrupt.h>

#include <stdio.h>
#include "util/delay.h"
#include "uart.h"


#define Device_Write_address	0xD0				/* Define RTC DS1307 slave address for write operation */
#define Device_Read_address		0xD1				/* Make LSB bit high of slave address for read operation */
#define TimeFormat12			0x40				/* Define 12 hour format */
#define AMPM					0x20

int second,minute,hour,day,date,month,year;

void TWI_init_master(void) // Function to initialize master
{
	TWBR0=127;    // Bit rate
	TWSR0= (1<<TWPS1)|(1<<TWPS0);    // Setting prescalar bits
	// SCL freq= F_CPU/(16+2(TWBR).4^TWPS)
}


								
uint8_t  I2C_Start(char write_address);			/* I2C start function */
uint8_t  I2C_Repeated_Start(char read_address);	/* I2C repeated start function */
void I2C_Stop();								/* I2C stop function */
void I2C_Start_Wait(char write_address);		/* I2C start wait function */
uint8_t  I2C_Write(char data);					/* I2C write function */
int I2C_Read_Ack();							/* I2C read ack function */
int I2C_Read_Nack();							/* I2C read nack function */

void RTC_Read_Clock(char read_clock_address)
{
	I2C_Start(Device_Write_address);				/* Start I2C communication with RTC */
	I2C_Write(read_clock_address);					/* Write address to read */
	I2C_Repeated_Start(Device_Read_address);		/* Repeated start with device read address */

	second = I2C_Read_Ack();						/* Read second */
	minute = I2C_Read_Ack();						/* Read minute */
	hour = I2C_Read_Nack();							/* Read hour with Nack */
	I2C_Stop();										/* Stop i2C communication */
}

void RTC_Read_Calendar(char read_calendar_address)
{
	I2C_Start(Device_Write_address);
	I2C_Write(read_calendar_address);
	I2C_Repeated_Start(Device_Read_address);

	day = I2C_Read_Ack();							/* Read day */
	date = I2C_Read_Ack();							/* Read date */
	month = I2C_Read_Ack();							/* Read month */
	year = I2C_Read_Nack();							/* Read the year with Nack */
	I2C_Stop();										/* Stop i2C communication */
}

int main(void)
{
	char buffer[20];
	const char* days[7]= {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
	UART_Init();
	TWI_init_master();
	sei();
	
	I2C_Start(Device_Write_address);				/* Start I2C communication with RTC */
	I2C_Write(0);					/* Write address to read */
	I2C_Write(0x00);	//sec
	I2C_Write(0x00);	//min			/* Write address to read */
	I2C_Write(0x17);	//hour
	I2C_Write(0x03);	//tuesday
	I2C_Write(0x23);	//day
	I2C_Write(0x09);	//month
	I2C_Write(0x21);	//year
	I2C_Stop();										/* Stop i2C communication */
	

 

    
	while(1)
    {
        //TODO:: Please write your application code 
		RTC_Read_Clock(0);
		//UART_Transmit(second);
		sprintf(buffer, "\n%02x:%02x:%02x  ", (hour & 0b00011111), minute, second);
		UART_SendString(buffer);
		RTC_Read_Calendar(3);
		sprintf(buffer, "%02x/%02x/%02x %s", date, month, year,days[day-1]);
		UART_SendString(buffer);
		_delay_ms(1000);
    }
}

uint8_t I2C_Start(char write_address)						/* I2C start function */
{
	uint8_t status;											/* Declare variable */
	TWCR0 = (1<<TWSTA)|(1<<TWEN)|(1<<TWINT);					/* Enable TWI, generate start condition and clear interrupt flag */
	while (!(TWCR0 & (1<<TWINT)));							/* Wait until TWI finish its current job (start condition) */
	status = TWSR0 & 0xF8;									/* Read TWI status register with masking lower three bits */
	if (status != 0x08)										/* Check weather start condition transmitted successfully or not? */
	return 0;												/* If not then return 0 to indicate start condition fail */
	TWDR0 = write_address;									/* If yes then write SLA+W in TWI data register */
	TWCR0 = (1<<TWEN)|(1<<TWINT);							/* Enable TWI and clear interrupt flag */
	while (!(TWCR0 & (1<<TWINT)));							/* Wait until TWI finish its current job (Write operation) */
	status = TWSR0 & 0xF8;									/* Read TWI status register with masking lower three bits */
	if (status == 0x18)										/* Check weather SLA+W transmitted & ack received or not? */
	return 1;												/* If yes then return 1 to indicate ack received i.e. ready to accept data byte */
	if (status == 0x20)										/* Check weather SLA+W transmitted & nack received or not? */
	return 2;												/* If yes then return 2 to indicate nack received i.e. device is busy */
	else
	return 3;												/* Else return 3 to indicate SLA+W failed */
}

uint8_t I2C_Repeated_Start(char read_address)				/* I2C repeated start function */
{
	uint8_t status;											/* Declare variable */
	TWCR0 = (1<<TWSTA)|(1<<TWEN)|(1<<TWINT);					/* Enable TWI, generate start condition and clear interrupt flag */
	while (!(TWCR0 & (1<<TWINT)));							/* Wait until TWI finish its current job (start condition) */
	status = TWSR0 & 0xF8;									/* Read TWI status register with masking lower three bits */
	if (status != 0x10)										/* Check weather repeated start condition transmitted successfully or not? */
	return 0;												/* If no then return 0 to indicate repeated start condition fail */
	TWDR0 = read_address;									/* If yes then write SLA+R in TWI data register */
	TWCR0 = (1<<TWEN)|(1<<TWINT);							/* Enable TWI and clear interrupt flag */
	while (!(TWCR0 & (1<<TWINT)));							/* Wait until TWI finish its current job (Write operation) */
	status = TWSR0 & 0xF8;									/* Read TWI status register with masking lower three bits */
	if (status == 0x40)										/* Check weather SLA+R transmitted & ack received or not? */
	return 1;												/* If yes then return 1 to indicate ack received */
	if (status == 0x20)										/* Check weather SLA+R transmitted & nack received or not? */
	return 2;												/* If yes then return 2 to indicate nack received i.e. device is busy */
	else
	return 3;												/* Else return 3 to indicate SLA+W failed */
}

void I2C_Stop()												/* I2C stop function */
{
	TWCR0=(1<<TWSTO)|(1<<TWINT)|(1<<TWEN);					/* Enable TWI, generate stop condition and clear interrupt flag */
	while(TWCR0 & (1<<TWSTO));								/* Wait until stop condition execution */
}

void I2C_Start_Wait(char write_address)						/* I2C start wait function */
{
	uint8_t status;											/* Declare variable */
	while (1)
	{
		TWCR0 = (1<<TWSTA)|(1<<TWEN)|(1<<TWINT);				/* Enable TWI, generate start condition and clear interrupt flag */
		while (!(TWCR0 & (1<<TWINT)));						/* Wait until TWI finish its current job (start condition) */
		status = TWSR0 & 0xF8;								/* Read TWI status register with masking lower three bits */
		if (status != 0x08)									/* Check weather start condition transmitted successfully or not? */
		continue;											/* If no then continue with start loop again */
		TWDR0 = write_address;								/* If yes then write SLA+W in TWI data register */
		TWCR0 = (1<<TWEN)|(1<<TWINT);						/* Enable TWI and clear interrupt flag */
		while (!(TWCR0 & (1<<TWINT)));						/* Wait until TWI finish its current job (Write operation) */
		status = TWSR0 & 0xF8;								/* Read TWI status register with masking lower three bits */
		if (status != 0x18 )								/* Check weather SLA+W transmitted & ack received or not? */
		{
			I2C_Stop();										/* If not then generate stop condition */
			continue;										/* continue with start loop again */
		}
		break;												/* If yes then break loop */
	}
}

uint8_t I2C_Write(char data)								/* I2C write function */
{
	uint8_t status;											/* Declare variable */
	TWDR0 = data;											/* Copy data in TWI data register */
	TWCR0 = (1<<TWEN)|(1<<TWINT);							/* Enable TWI and clear interrupt flag */
	while (!(TWCR0 & (1<<TWINT)));							/* Wait until TWI finish its current job (Write operation) */
	status = TWSR0 & 0xF8;									/* Read TWI status register with masking lower three bits */
	if (status == 0x28)										/* Check weather data transmitted & ack received or not? */
	return 0;												/* If yes then return 0 to indicate ack received */
	if (status == 0x30)										/* Check weather data transmitted & nack received or not? */
	return 1;												/* If yes then return 1 to indicate nack received */
	else
	return 2;												/* Else return 2 to indicate data transmission failed */
}

int I2C_Read_Ack()											/* I2C read ack function */
{
	TWCR0=(1<<TWEN)|(1<<TWINT)|(1<<TWEA);					/* Enable TWI, generation of ack and clear interrupt flag */
	while (!(TWCR0 & (1<<TWINT)));							/* Wait until TWI finish its current job (read operation) */
	return TWDR0;											/* Return received data */
}

int I2C_Read_Nack()										/* I2C read nack function */
{
	TWCR0=(1<<TWEN)|(1<<TWINT);								/* Enable TWI and clear interrupt flag */
	while (!(TWCR0 & (1<<TWINT)));							/* Wait until TWI finish its current job (read operation) */
	return TWDR0;											/* Return received data */
}
Posted on Leave a comment

How to use UART Receive complete ISR of ATmega328PB using microchip studio

When you enable the communication using the UART. You have the flexibility to either use the Polling or Interrupt method to continue with your programming.

Polling halts the execution of the program and waits for the UART peripheral to receive something so that program execution must continue. But it eats a lot of the computing time.

So, Interrupt Service Routine is written and implemented such the program execution does not stop. It will stop when there is an interrupt and when there is data in the UDR0 register of UART. Then the ISR will execute and then transfer the control to the main program. Which saves a lot of computing time.

you have to add an interrupt library in your program.

#include <avr/interrupt.h>

Then you need to enable the Global interrupt flag.

.
.
.
int main()
{
.
.
.
sei();            // This is Set Enable Interryupt

   while(1)
  {
     // This is your application code.
   }

}

Then you need to enable the UART receive complete interrupt. by setting ‘1’ to RXCIE0 bit of USCR0B register.

Write the ISR function which takes “USART0_RX_vect” as the argument.

char Received_char;
ISR(USART0_RX_vect)
{
	Received_char = UDR0;
}

int main()
{
UCSR0B = (1 << RXCIE0)|(1<<RXEN0)|(1<<TXEN0); 
.
.
.
sei();
while(1);
{
}

}

The above code shows you how to implement UART receive complete ISR. It is not a full initialisation code. You still have to write the UBRR and the frame control to enable the uart peripheral.

Posted on Leave a comment

How to use internal temperature sensor of ATmega328pb

ATmega328PB is a new semiconductor microcontroller from Microchip semiconductors. I have used its previous generation which is ATmega328 and ATmega328P. They were usually found on Arduino Uno and Arduino nano.

This new IC has a temperature sensor built into it. Which is handy for measuring the die temperature. Which can make device stable in high-temperature design. It is not accurate as a dedicated temperature sensor. But it gives you a rough idea. Using this you can the processes.

It is not an Ambient temperature Sensor.

/*
 * main.c
 *
 * Created: 8/15/2022 4:06:41 PM
 *  Author: abhay
 */ 
#define F_CPU 16*1000000
#include <xc.h>
#include "uart.h"
#include "util/delay.h"
#include <stdlib.h>
long Ctemp;
unsigned int Ftemp;

int main(void)
{
		DDRD &= ~(1 << DDD0);							// PD0 - Rx Input
		DDRD |= (1 << DDD1);							// PD1 - Tx Ouput
		USART_Init();
		
	/* Replace with your application code */
	ADMUX = (1<<REFS1) | (1<<REFS0) | (0<<ADLAR) | (1<<MUX3) | (0<<MUX2) | (0<<MUX1) | (0<<MUX0);
	ADCSRA =  (1<<ADPS2) |(1<<ADPS1) | (1<<ADEN);
	
	ADCSRA |= (1<<ADSC);
	
	while ((ADCSRA & (1<<ADSC)) !=0);
	
	while (1)
	{
		ADCSRA |= (1<<ADSC);
		while ((ADCSRA & (1<<ADSC)) !=0);
		
		Ctemp = ((ADC - 247)/1.22)*1000;
		Ftemp = (Ctemp * 1.8) + 32;
		
		USART_Transmit( (((int)Ctemp/100000)%10) + 48);
		USART_Transmit( (((int)Ctemp/10000)%10) + 48);
		USART_Transmit( (((int)Ctemp/1000)%10) + 48);
		USART_Transmit('.');
		USART_Transmit( (((int)Ctemp/100)%10) + 48);
		USART_Transmit( (((int)Ctemp/10)%10) + 48);
		USART_Transmit( ((int)Ctemp%10) + 48);
		
		USART_Transmit('\n');
		_delay_ms(1000);
	}
	return -1;
}
Posted on Leave a comment

How to add USBASP as External Tool in Microchip studio

Download microchip studio from here https://www.microchip.com/en-us/tools-resources/develop/microchip-studi

Install the program.

I use USBASP to program AVR ATmega328pb.

Go to Tools > External Tools > ADD

Command: location of avrdude

C:\WinAVR-20100110\bin\avrdude.exe

Arguments:

-c usbasp -p m328pb -U flash:w:$(ProjectDir)Debug\$(TargetName).hex:i

Check the Use Output window to be able to see the output of the avrdude inside the microchip studio terminal.

Posted on Leave a comment

How to set up UART of ATmega328pb in Atmel Studio 7.0

To set up uart in Atmel studio 7.0.

Firstly you will need a common baud rate.

Then you go to section 24.11 of the datasheet. You will find common calculated values for the UBRRn register.

UBRRn register is comprised of high and low registers.

First, you have to initialise the Data direction registers for the RX and Tx Pins. Then you initialise the UART peripheral.

DDRD &= ~(1 << DDD0);				// PD0 - Rx Input
DDRD |= (1 << DDD1);				// PD1 - Tx Ouput
USART_Init();					// UART intialise

Here is the basic UART library code.

/*
* Name: UART library Code
*/
void USART_Init( )
{
	/*Set baud rate */
	
	UBRR0L = 103;
	/* Enable receiver and transmitter */
	UCSR0B = (1 << RXCIE0)|(1<<RXEN0)|(1<<TXEN0);
	/* Set frame format: 8data, 1stop bit */
	UCSR0C = (3<<UCSZ00);
}

void USART_Transmit(uint8_t data )
{
	
	/* Wait for empty transmit buffer */
	while ( !( UCSR0A & (1<< UDRE0 )) )
	;
	/* Put data into buffer, sends the data */
	UDR0 = data;
	
}

unsigned char USART_Receive( void )
{
	/* Wait for data to be received */
	while ( !(UCSR0A & (1<<RXC0)) )
	;
	/* Get and return received data from buffer */
	return UDR0;
}

void USART_SendString(char *str)
{
	unsigned char j=0;
	
	while (str[j]!=0)		/* Send string till null */
	{
		USART_Transmit(str[j]);
		j++;
	}
}
Posted on Leave a comment

How to ATMega328PB to avrdude.conf

I recently bought a few Arduino Uno clones. They were not cheap. They utilise the ch34 IC, which is a USB to UART solution. They all have SMD atmega328pb soldered on them.

The problem is that two of them stopped working with the Arduino ide. On inspection, i found out that my software was not updated so firstly I updated the software which now includes a configuration for the atmega328pb.

But somehow the internal bootloader in these SMD chips got corrupted and it stopped working. I then probed the chip with AVRdude prograamer.

Found that the chip is atmega328pb. The configurations were not included at the time of installation. But the avrdude program allows you added other avr parts from Atmel.

For Windows 10

  1. Go to
C:\WinAVR-20100110\bin

2. Then open

Posted on Leave a comment

STM32F429I-DISC1

Datasheet for stm32F429ZI https://www.st.com/en/microcontrollers-microprocessors/stm32f429zi.html

This board have a 2.4 Resistive touch TFT LCD. which uses the ILI9341  controller.

The touch screen which I got with this display is very bad. you have to press down on the screen before you power ON the device.

The microcontroller is based on the ARM CORTEX M4F which can be clocked up to 180MHz. This particular board has an 8Mbyte of SDRAM included which is basically useless with this screen. If you want to see the full potential you have to use the LTDC peripheral which when configured with DMA2D gives you a very powerful development board with multimedia capabilites.

Posted on Leave a comment

STM32F746IGT6 – An ARM CORTEX M7 Based Microcontroller

Datasheet

It’s an ARM Cortex M7 based microcontroller which has a maximum clock speed of 216Mhz.

Well, it has a few peripherals which when combined with its CPU, makes it a very powerful controller.

Those peripherals are LTDC, SDRAM Controller.

It also has the usual set of peripherals from the ST. But these in particular makes it a very powerful microcontroller.

Posted on Leave a comment

How to redirect printf() to USART in STM32f103RB using STM32Cube IDE

Printf() function can be redirected to USART and also towards SWO.

Here you will see how to redirect printf() to USART in STM32f103RB

You need to rewrite this code in your main.c file

/*
* Function Name: _write
* Function Description: Redirect the printf() statement towards the UART using the HAL_UART_Transmit
Author: Abhay

*/
int _write(int fd, char* ptr, int len) {
    HAL_UART_Transmit(&huart1, (uint8_t *) ptr, len, HAL_MAX_DELAY);
    return len;
}

If you have created your project using STM32CubeMX or STM32 Cube IDE, then you can rewrite it in between USER CODE BEGIN 0 as shown

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
int _write(int fd, char* ptr, int len) {
    HAL_UART_Transmit(&huart1, (uint8_t *) ptr, len, HAL_MAX_DELAY);
    return len;
}
/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */

  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */

  }
  /* USER CODE END 3 */
}

After adding the code, connect the uart to your laptop or computer using serial to USB adapter and open serial Terminal application like YAT.
Then you will be able to see printf message over there.