AVR EEPROM issue in proteus - avr

When I'm using Proteus to simulate following program, The EEPROM will not change, and Also the EEPE will not set when I add EECR to watch, The whole program is here:
#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <util/delay.h>
void writeEEPROM(unsigned char address,char data){
while(EECR & (1<<EEPE)); //wait for previus writing;
EECR = ((0<<EEPM1)|(0<<EEPM0));
//EECR=0;
EEAR = address; //set address to eeprom address register
EEDR = data;
cli();
EECR |= (1<<EEMPE);
EECR |= (1<<EEPE);
while(EECR & (1<<EEPE)); //wait for previus writing;
EECR |= (1<<EEMPE);
EECR |= (1<<EEPE);
sei();
}
char readEEPROM(unsigned char address){
while(EECR & (1<<EEPE)); //wait for previous write operation
EEAR=0;
EEAR |= address;
EECR=0;
EECR |= 1; //set bit0
return EEDR;
}
int main()
{
// Write your code here
char ret=0;
writeEEPROM(1,9);
_delay_ms(100);
ret=readEEPROM(1);
if(ret==9){
DDRB=0xff;
PORTB=0xff;
}
while (1)
;
return 0;
}
On calling writeEEPROM data will not store to the eeprom.

This is from the source code companion fileset to AVR103 AVR EEPROM Application Note, authoritative publication from the device manufacturer.
char EEPROM_GetChar( unsigned int addr )
{
do {} while( EECR & (1<<EEPE) ); // Wait for completion of previous write.
EEAR = addr; // Set EEPROM address register.
EECR = (1<<EERE); // Start EEPROM read operation.
return EEDR; // Return the byte read from EEPROM.
}
void EEPROM_PutChar( unsigned int addr, char new_value )
{
char old_value; // Old EEPROM value.
char diff_mask; // Difference mask, i.e. old value XOR new value.
unsigned char old_interrupt; // Stores interrupt flag while programming.
old_interrupt = __save_interrupt(); // Save interrupt flag state.
__disable_interrupt(); // Ensure atomic operation for the write operation.
do {} while( EECR & (1<<EEPE) ); // Wait for completion of previous write.
#ifndef EEPROM_IGNORE_SELFPROG
do {} while( SPMCSR & (1<<SELFPRGEN) ); // Wait for completion of SPM.
#endif
EEAR = addr; // Set EEPROM address register.
EECR = (1<<EERE); // Start EEPROM read operation.
old_value = EEDR; // Get old EEPROM value.
diff_mask = old_value ^ new_value; // Get bit differences.
// Check if any bits are changed to '1' in the new value.
if( diff_mask & new_value ) {
// Now we know that _some_ bits need to be erased to '1'.
// Check if any bits in the new value are '0'.
if( new_value != 0xff ) {
// Now we know that some bits need to be programmed to '0' also.
EEDR = new_value; // Set EEPROM data register.
EECR = (1<<EEMPE) | // Set Master Write Enable bit...
(0<<EEPM1) | (0<<EEPM0); // ...and Erase+Write mode.
EECR |= (1<<EEPE); // Start Erase+Write operation.
} else {
// Now we know that all bits should be erased.
EECR = (1<<EEMPE) | // Set Master Write Enable bit...
(1<<EEPM0); // ...and Erase-only mode.
EECR |= (1<<EEPE); // Start Erase-only operation.
}
} else {
// Now we know that _no_ bits need to be erased to '1'.
// Check if any bits are changed from '1' in the old value.
if( diff_mask ) {
// Now we know that _some_ bits need to the programmed to '0'.
EEDR = new_value; // Set EEPROM data register.
EECR = (1<<EEMPE) | // Set Master Write Enable bit...
(1<<EEPM1); // ...and Write-only mode.
EECR |= (1<<EEPE); // Start Write-only operation.
}
}
__restore_interrupt( old_interrupt ); // Restore interrupt flag state.
}
void main()
{
char t; // Temporary byte.
unsigned int addr = 0x10; // EEPROM address to use.
// Test the EEPROM_GetChar() function.
t = EEPROM_GetChar( addr );
// Try erasing the whole byte.
EEPROM_PutChar( addr, 0xff );
// Try changing a few bits to '0'.
EEPROM_PutChar( addr, 0x0f );
// Try changing bits both ways.
EEPROM_PutChar( addr, 0xf0 );
// Try changing nothing.
EEPROM_PutChar( addr, 0xf0 );
// Restore old value.
EEPROM_PutChar( addr, t );
for(;;); // Loop forever.
}

Related

Issue with Interfacing atmega328p with Bluetooth

I’m trying to interface atmega328p with Blutooth HC-0.
I was following the example in Atmega328P datasheet in USART section.
The code is simply trying to send a letter 'b' to Bluetooth terminal on mobile phone and receive a letter. If the received letter is 'a', an LED on PORTB0 will turn on, if the letter is 'c', the LED will turn off. But unfortunately nothing is working.
Connection between atmega328P and HC-05 is as follows:
HC-05 -> Atmega328P
RXD -> pin3
TXD -> pin2
GND -> pin8
VCC -> pin7
Bluetooth light is turning on and off, and is connected successfully to mobile phone but no data is received, and when the letters 'a' and 'c' are sent nothing happens with LED connected to PORTB0.
The code is shown here. Thank you for any help!
#define F_CPU 16000000UL // Clock Speed
#define BAUD 9600
#define MYUBRR F_CPU/16/BAUD-1
#include <stdint.h>
#include <avr/io.h>
#include <util/delay.h>
char data;
char data2 = 'b';
void USART_Init(unsigned int ubrr)
{
/* Set baud rate */
UBRR0H = (unsigned char)(ubrr>>8);
UBRR0L = (unsigned char)(ubrr);
/* Enable receiver and transmitter */
UCSR0B = (1<<RXEN0)|(1<<TXEN0);
/* Set frame format: 8data, 2stop bit */
UCSR0C = (1<<USBS0)|(3<<UCSZ00);
}
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_Transmit(char data)
{
/* Wait for empty transmit buffer */
while ( !( UCSR0A & (1<<UDRE0)) );
/* Put data into buffer, sends the data */
UDR0 = data;
}
int main(void)
{
DDRB = 0b00000001;
PORTB = 0b00000000;
USART_Init(MYUBRR);
while (1) {
data = USART_Receive();
USART_Transmit(data2);
if (data == 'a') {
PORTB = 0b00000001;
} else if (data == 'c') {
PORTB = 0b00000000;
}
}
}

AVR Atmega32a USART library isn't working

/*
RC_Car_AVR.c
Created: 4/18/2018 7:55:07 PM
Author :
*/
#define F_CPU 16000000
#define BAUD 9600
#define TUBRR (((F_CPU / 16) / BAUD) - 1)
#include <avr/io.h>
#include <util/delay.h>
char Read;
void USART_Init(void){
UBRRL = TUBRR;
UCSRB = (1<<TXEN)|(1<<RXEN);
UCSRC = (1<<UCSZ1)|(1<<UCSZ0);
}
char USART_Receive(void){
/* Wait for data to be received */
while (!(UCSRA & (1<<RXC)));
/* Get and return received data from buffer */
return UDR;
}
int main(void){
USART_Init();
DDRB |= (1<<0);
PORTB |= (1<<0);
while (1){
Read = USART_Receive();
if(Read == 'F'){
PORTB ^= (1<<0);
_delay_ms(100);
}
}
}
I'm trying to toggle an LED when I receive a certain character through the Bluetooth module (HC05).
I've written the USART library just like the datasheet but it doesn't seem to work (I'm only concerned with the initialization and receiving code since I'm working on a half duplex system so i don't need the transmition part).
I'm using Atmega32a with a 16MHz external crystal Oscillator.
Please tell me if you find anything wrong.
Thanks in advance.
Your Initialization is wrong.
Try this
void USART_Init(void){
UBRRL = TUBRR;
UBRRH = TUBRR >> 8;
UCSRB = (1<<TXEN)|(1<<RXEN);
UCSRC = (1<<UCSZ1)|(3<<UCSZ0);
}
This is the following initialization code provided in data sheet of atmega32
void USART_Init( unsigned int baud )
{
/* Set baud rate */
UBRRH = (unsigned char)(baud>>8);
UBRRL = (unsigned char)baud;
/* Enable receiver and transmitter */
UCSRB = (1<<RXEN)|(1<<TXEN);
/* Set frame format: 8data, 2stop bit */
UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);
}
I know following datasheet is little overhead in beginning But eventually you will see all your answers are provided there.

setting an i2c register to high

I have this project that my boss asked me to do and the first step is to figure out how to set a given I2C register to high or low using the silicon lab library, if anyone knows any good sources for this type of problem please provide them thank you. The pic that I am using is the pic16f1823, I've already looked at the documentation of the pic but into only states how to read and write to an I2c.
I use this as a header file and seems to work well for PIC16F1827 which is basically the same as the 1823. It used the peripheral of the PIC. Just include in in any c file you want to use i2c in. Make sure you #define FOSC in order to calculate the correct baud rate. Also double check the port and tris assignments are correct for your device and make adjustments.
It uses polling instead of an interrupt. Uncomment the interrupt setup code and write an interrupt service routine to catch the interrupts.
#ifndef I2C_H
#define I2C_H
#ifdef __cplusplus
extern "C" {
#endif
/*
* Hi-Tech C I2C library for 12F1822
* Master mode routines for I2C MSSP port to read and write to slave device
* Copyright (C)2011 HobbyTronics.co.uk 2011
* Freely distributable.
*/
#define I2C_WRITE 0
#define I2C_READ 1
// Initialise MSSP port. (12F1822 - other devices may differ)
void i2c_Init(void){
// Initialise I2C MSSP
// Master 100KHz
TRISB2 = 1;
TRISB5 = 1;
SSP1CON1 = 0b00101000; // I2C Master mode
SSP1CON2 = 0b00000000;
SSP1CON3 = 0b00000000;
//SSP1MSK = 0b00000000;
SSP1ADD = I2C_BRG; // clock = FOSC/(4 * (SSPxADD+1))
//SSP1IE = 1; // enable interrupt
SSP1STAT = 0b10000000;
}
// i2c_Wait - wait for I2C transfer to finish
void i2c_Wait(void){
while ( ( SSP1CON2 & 0x1F ) || ( SSPSTAT & 0x04 ) );
}
// i2c_Start - Start I2C communication
void i2c_Start(void)
{
i2c_Wait();
SSP1CON2bits.SEN=1;
}
// i2c_Restart - Re-Start I2C communication
void i2c_Restart(void){
i2c_Wait();
SSP1CON2bits.RSEN=1;
}
// i2c_Stop - Stop I2C communication
void i2c_Stop(void)
{
i2c_Wait();
SSP1CON2bits.PEN=1;
}
// i2c_Write - Sends one byte of data
void i2c_Write(unsigned char data)
{
i2c_Wait();
SSPBUF = data;
}
// i2c_Address - Sends Slave Address and Read/Write mode
// mode is either I2C_WRITE or I2C_READ
void i2c_Address(unsigned char address, unsigned char mode)
{
unsigned char l_address;
l_address=address<<1;
l_address+=mode;
i2c_Wait();
SSPBUF = l_address;
}
// i2c_Read - Reads a byte from Slave device
unsigned char i2c_Read(unsigned char ack)
{
// Read data from slave
// ack should be 1 if there is going to be more data read
// ack should be 0 if this is the last byte of data read
unsigned char i2cReadData;
i2c_Wait();
SSP1CON2bits.RCEN=1;
i2c_Wait();
i2cReadData = SSPBUF;
i2c_Wait();
if ( ack ) SSP1CON2bits.ACKDT=0; // Ack
else SSP1CON2bits.ACKDT=1; // NAck
SSP1CON2bits.ACKEN=1; // send acknowledge sequence
return( i2cReadData );
}
#ifdef __cplusplus
}
#endif
#endif /* I2C_H */
Then you can use the higher level functions defined above to control a device, which is described in the datasheet of the slave device.
For example, to read from an eeprom:
#include <xc.h>
#define FOSC 16000000
#include "i2c.h"
unsigned char i2c_read_eeprom( unsigned char slaveaddress, unsigned char memaddress )
{
unsigned char data;
data = 123;
i2c_Start();
i2c_Address( slaveaddress, I2C_WRITE);
i2c_Write(memaddress);
if( SSP1CON2bits.ACKSTAT )
txstring("ACK!\r\n");
else txstring("nACK!\r\n");
i2c_Start();
i2c_Address( slaveaddress, I2C_READ);
data = i2c_Read(0);
i2c_Stop();
return data;
}

AVR studio7 declaration error

i need your help
i am trying atmega128a using AVR studio 7
but one problem is there
when i control DDRB and PORTB into main()
it works fine
but if i control DDRB and PORTB out of main()
if becomes error
'expected identifier or '(' before volatile'
i just want to know that why always handing DDRB and PORTB is only in main()
here is my code
#define F_CPU 14745600UL
#include <avr/io.h>
#include <util/delay.h>
DDRB = 0xFF;
PORTB = 0x00;
int main(void)
{
/* Replace with your application code */
PORTB = 0x01;
_delay_ms(300);
while (1)
{
PORTB <<= 1;
_delay_ms(300);
if(PORTB == 0x80){
PORTB = 0x01;
_delay_ms(300);
}
}
}
C is not a scripting language. Any line of code that actually runs must be inside a function. You can make a new function and call it from main.
They need to be assigned inside of a function because they are macros that end up getting replaced with something that looks like this:
(*(volatile uint8_t *)<address>)
where <address> is a memory address that corresponds to the register that you are trying to access. You are trying to cast and dereference a pointer, which is not a valid operation outside of a function.

Need to read analog input to a pic16f688 using mplab and xc8 compiler

I am using a PIC16f688 to try to read analog input and to turn a light on or off based on the voltage read. Using this PIC, I have successfully gotten the light to blink using on and off. Here is the code I used for that.
void main() {
ANSEL = 0b00000000; //All I/O pins are configured as digital
CMCON0 = 0x07; // Disbale comparators
TRISC = 0b00000000; // PORTC All Outputs
TRISA = 0b00001000; // PORTA All Outputs, Except RA3
do {
RC0 = 1;
__delay_ms(500);
RC0 = 0;
__delay_ms(500);
} while (1); // Infinite Loop
}
After reading different things I ended up with this code to try to read the analog input.
#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = OFF // Brown-out Reset Enable bit (BOR disabled)
#pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
#include <xc.h>
#include <pic16f688.h>
#define _XTAL_FREQ 8000000
void main() {
int voltage;
ANSEL = 0b01000000; //All I/O pins are configured as digital except an6/RC2
TRISC = 0b00000100; // PORTC All Outputs except RC2
TRISA = 0b00001000; // PORTA All Outputs, Except RA3
do {
ADCON0 = 0xbb; //set to read
GO_nDONE = 1;
while(GO_nDONE == 1);
voltage = (ADRESH << 8) + ADRESL; //get voltage reading
if(voltage > 500){ //if voltage is greater than 500 out of 1023 turn light on
RC0 = 1;
}
else{
RC0 = 0;
}
__delay_ms(500);
} while (1); // Infinite Loop
}
When I run this, the light is on no matter what the input is, including when the input is wired to ground.
I am using XC8 compiler in MPLab.
I hope that you are using external oscillator otherwise you have set wrong internal oscillator!
Default ADC clock is Fosc/2 and is to high for 8Mhz, so set the ADCON1 to Fosc/16 check datasheet.
Why did you remove this line?
CMCON0 = 0x07; // Disbale comparators
It is essential!
Try disabling the comparators using CMCON0 = 0x07; then RC0 should function normally.

Resources