24c32a eeprom write operation not working with attiny402..am i mistaken? - c

#define sda_on PORTA_DIRSET = PIN1_bm ; PORTA_OUTSET = PIN1_bm ;
#define sda_read PORTA_DIRCLR = PIN1_bm ;while(PORTA_IN & (PIN1_bm));PORTA_DIRSET = PIN1_bm ;
#define sda_off PORTA_DIRSET = PIN1_bm ;PORTA_OUTCLR = PIN1_bm ;
#define scl_on PORTA_DIRSET = PIN2_bm ;PORTA_OUTSET = PIN2_bm ;
#define scl_off PORTA_DIRSET = PIN2_bm ;PORTA_OUTCLR = PIN2_bm ;
#include <xc.h>
#include <util/delay.h>
void i2c_start(void)
{
sda_on;
scl_on;
_delay_ms(10);
sda_off;
_delay_ms(10);
scl_off;
}
void i2c_stop(void)
{
sda_off;
scl_off;
_delay_ms(10);
scl_on;
_delay_ms(10);
sda_on;
}
void i2c_data_write(unsigned char data)
{
for(int i=0;i<8;i++)
{
if(data & 0x80)
{
sda_on;
}
else sda_off;
_delay_ms(10);
scl_on;
_delay_ms(10);
scl_off;
data = data << 1;
}
scl_on;
sda_on;
_delay_ms(10);
sda_read;
_delay_ms(10);
scl_off;
_delay_ms(10);
}
Its a just write operation in 24c32a eeprom using by Attiny402..its not working ..im using simulating with debugging by proteus software....i2c debugger gives always question mark while im run the simulation help me..

a quick answer: those macros should be changed to use bit-wise-OR assignment |= and bit-wise-AND assignment &= instead.
#define sda_on PORTA_DIRSET = PIN1_bm ; PORTA_OUTSET = PIN1_bm ;
#define scl_on PORTA_DIRSET = PIN2_bm ;PORTA_OUTSET = PIN2_bm ;
The macro sda_on sets PORTA_OUTSET to the value PIN1_bm, while the macro scl_on sets PORTA_OUTSET to the value PIN2_bm.
From those macros, we know the two pins sda and scl are both on PORTA, and the macros operate with bit-mask for the two pins. In general, a bit-mask of port pin would have only one bit set, like 0x01 or 0x02 or 0x04, and so on.
Then, at the beginning of i2c_start(), a sda_on is followed by a scl_on, that makes the value of PORTA set to PIN2_bm but not the correct value PIN1_bm | PIN2_bm which will set both pins to high level for the setup-time of a start-condition of i2c.
void i2c_start(void)
{
sda_on; // PORTA_DIRSET = PIN1_bm ; PORTA_OUTSET = PIN1_bm ;
scl_on; // PORTA_DIRSET = PIN2_bm ;PORTA_OUTSET = PIN2_bm ;
// at this point, PORTA_DIRSET = PIN2_bm ;PORTA_OUTSET = PIN2_bm ;
// But not, PORTA_DIRSET = PIN1_bm | PIN2_bm ;PORTA_OUTSET = PIN1_bm | PIN2_bm ;
_delay_ms(10);
sda_off;
_delay_ms(10);
scl_off;
}
So, the rough solution is to change the macros like the followings.
#define scl_on PORTA_DIRSET |= PIN2_bm ;PORTA_OUTSET |= PIN2_bm ;
#define scl_off PORTA_DIRSET &= ~PIN2_bm ;PORTA_OUTCLR &= ~PIN2_bm ;
Or, you could use two ports for the two pins, like sda on PORTA and scl on PORTB, if there is no other pin sharing the same port, then the bit-wise-OR assignment |= and bit-wise-AND assignment &= would be not necessary.

Related

KEIL4 where the lpc2148 ADC Interrupts or IRQs wont execute

I have configured for the ADC channel AD0.1 of processor LPC 2148, with ISR. But while ADC value changes ISR is not executing. Because of this VICVectAddr contains the value of ISR function. This program is part of learning.
Please find the Code below. It is very help full if anybody has given solution
#include <lpc214x.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#define SBIT_RESULT 6u
#define SBIT_CLCKDIV 8u
#define SBIT_BURST 16u
#define SBIT_START 24u
#define SBIT_PDN 21u
#define SBIT_EDGE 27u
#define SBIT_DONE 31u
void ADC_Init (void);
__irq void ADC_ISR (void) ;
void main(void) {
AD0CR=0x0;
ADC_Init ();
while(1){
}
}
void ADC_Init (void)
{
PINSEL1 = 0x01000000 ; // ADC P0.28, AD0.1
AD0INTEN =0x02; //On completetion of ADC channel 1 generate interupt
VICVectAddr5 = (unsigned int)ADC_ISR; // address of the ISR
VICVectCntl5 = (1<<5) | 18;
VICIntSelect &= ~ (1<<18);
VICIntEnable = (1<<18);
AD0CR = 0X00200D02;
AD0CR |= 0x01000000;
}
// Interrupt Service Routine-ISR
__irq void ADC_ISR(void) {
static int flag=0 ;
int val;
unsigned int data;
bool readStatus;
data = AD0GDR ;
readStatus = data & 0x80000000;
if(readStatus){
val = data >>=6;
val= val & 0x3FF;
val=((val/1023.0)*3.3);
}
Delay(1000000);
AD0INTEN =0x0; //clear ADC interrupt
VICVectAddr = 0;
}
```

CC430 UART Reading Problem -Receive Interrupt Flag is Always '0'

I'm trying to establish UART communication. I can send data from CC430F6137 to other MCU .However I couldn't handle receive operation. I'm sure that other MCU sends the data through UART Tx pin , but I couldn't get this datas from CC430 Rx pin.
My code is that :
#include <stdio.h>
#include <msp430.h>
#include "cc430x613x.h"
char buffer_0[5] ;
char terminal_read();
int main(void)
{
WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer
UART_open();
UCA0IE |= UCRXIE ;
while(1)
{
terminal_read();
// __delay_cycles(1e5);
}
return 0;
}
char terminal_read()
{
char c ;
while (!(UCA0IFG & UCRXIFG));
c = UCA0RXBUF ;
printf("%c" , &c);
return UCA0RXBUF;
}
void terminal_write(char *info)
{
unsigned int i;
unsigned int len = strlen(info) ;
for(i=0;i<len;i++)
{
UCA0TXBUF=info[i];
__delay_cycles(10000);
}
}
void UART_open()
{
P1SEL |= BIT5 + BIT6;
//UART Settings
UCA0CTL1 |= UCSWRST;
UCA0CTL1 |= UCSSEL0 ; // ACLK
UCA0BR0=3; //UCA0BR0 = 3 ; //32Khz / 9600 –>> 3
UCA0BR1=0; //UCA0BR1=0; // BAUD 9600; ( UCABR1 * 256 ) + UCABR0 = UCABRx see "slau259e.pdf"
UCA0MCTL=UCBRS0 + UCBRS1 ; // see "slau259e.pdf" page 602 //
//UCA0MCTL =| BIT7 | BIT6 | BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0 |
// |------- UCBRFx --------------|----UCBRSx----------|UCOS16|
// for 9600 baudrate at 32kHz UCBRFx = 0 , UCBRSx = 3 , UCOS16 = 0
// | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 |
// 0b00000110 = 0x06 = 6
UCA0CTL1 &=~ UCSWRST;//
// UCA0CTL1 |= UCDORM;
}
void UART_close()
{
P1SEL &= ~(BIT5 + BIT6);
P1DIR |= BIT5 + BIT6;
P1OUT &= ~(BIT5 + BIT6);
UCA0CTL1 |= UCSWRST;
UCA0CTL1 &=~ UCDORM;
}
char* String_int(int data)
{
char* ret_data;
ret_data = ltoa(data , buffer_0 , 10 );
return ret_data;
}
What's wrong with my code? I always read the UCRXIFG as '0'. So 'terminal_read' function always stuck on this line.
Since you are polling for the interrupt flag in the terminal_read() function, then you don't need to enable interrupt with UCA0IE |= UCRXIE; because that will cause the CPU to go to the interrupt vector, which your code doesn't provide. Instead, remove the UCA0IE |= UCRXIE; and continue polling.
Also, the printf() will go to the terminal of the Debug window only if you have the JTAG debugger attached, otherwise it could get stuck. I agree with Peter that it could get stuck here if you don't have the debugger attached. Try removing that and replace with an LED blinker so you know the terminal_read() isn't getting stuck.

Using 0xFF in an array of pointers

I don't understand the use of 0xFF in an array of pointers. I want to control a keypad. My code is:
// CONFIGURATION BITS
#pragma config FOSC = HS // Oscillator Selection bits (XT 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 LVP = OFF // Low-Voltage In-Circuit Serial Programming Enable bit
#pragma config CPD = OFF // Data EEPROM Memory Code Protection bit
#pragma config WRT = OFF // Flash Program Memory Write Enable bits
#pragma config CP = OFF // Flash Program Memory Code Protection bit
#define _XTAL_FREQ 8000000
// DEFINING LCD PINS
#define RS RD2
#define EN RD3
#define D4 RD4
#define D5 RD5
#define D6 RD6
#define D7 RD7
// DEFINING KEYPAD PINS
#define KP_R1 PORTBbits.RB1
#define KP_R2 PORTBbits.RB2
#define KP_R3 PORTCbits.RC1
#define KP_R4 PORTCbits.RC2
#define KP_C1 PORTBbits.RB3
#define KP_C2 PORTBbits.RB4
#define KP_C3 PORTBbits.RB6
#define KP_C4 PORTBbits.RB7
#include <xc.h>
#include "lcd.h"
#include <stdio.h>
#include <stdlib.h>
const char *keyPadMatrix[] =
{
"1","2","3","A",
"4","5","6","B",
"7","8","9","C",
"*","0","#","D",
0xFF
};
void kbd_init();
void kbd_init(){
// SETTING THE DATA DIRECTION REGISTERS
PORTB = 0x00;
TRISB = 0xD9; // RB7-1 RB6-1 RB5-0 RB4-1 RB3-1 RB2-0 RB1-0 RB0-1 ( 1=Input, 0=Output)
PORTC = 0x00;
TRISC = 0x90; // RC7-1 RC6-0 RC5-0 RC4-1 RC3-0 RC2-0 RC1-0 RC0-0 ( 1=Input, 0=Output)
OPTION_REGbits.nRBPU = 1;
}
char old_key;
char *kbd_getc();
char *kbd_getc(){
char row;
char key = 0;
for( row = 0b00000001; row < 0b00010000; row <<= 1 )
{
{ // turn on row output
KP_R1 = (row & 0x0001)>>0;
KP_R2 = (row & 0x0002)>>1;
KP_R3 = (row & 0x0004)>>2;
KP_R4 = (row & 0x0008)>>3;
__delay_ms(1);
}
// read colums - break when key press detected
if( KP_C1 == 1 ){
break;
}
key++;
if( KP_C2 == 1 ){
break;
}
key++;
if( KP_C3 == 1 ){
break;
}
key++;
if( KP_C4 == 1 ){
break;
}
key++;
}
KP_R1 = 0;
KP_R2 = 0;
KP_R3 = 0;
KP_R4 = 0;
if (key!=old_key){
old_key=key;
return keyPadMatrix[key];
}
else{
return keyPadMatrix[0x10];
}
}
void main()
{
TRISD = 0x00; //PORTD as output for LCD
Lcd_Init();
Lcd_Clear();
while(1)
{
Lcd_Set_Cursor(1,1);
char *keypress;
keypress = kbd_getc();
Lcd_Write_String(keypress);
__delay_ms(50);
}
}
The idea is that when you press a key, an LCD show that key, and when you don't press anything, the LCD doesn't show anything. If you change 0xFF for something like "w" the keypad does the trick, but instead of showing anything, it shows "w" (as expected). But when you use 0xFF the keypad doesn't work. I don't understand the use of 0xFF in the array of pointers. I copied the code from a website, but I making some changes because the original doesn't work either.
Note:
void Lcd_Write_String(char *a)
{
int i;
for(i=0;a[i]!='\0';i++)
Lcd_Write_Char(a[i]);
}

USART with ATMEGA168A -

I am trying to make a very simple USART program which send the received character back to the transmitter and represent the equivalent binary number by flashing 8 leds in my breadboard.
Here is the code:
#define F_CPU 1000000UL // set the CPU clock
#define BAUD 9600 // define baud
#define BAUDRATE ((F_CPU)/(BAUD*16UL)-1) // set baudrate value for UBRR
#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>
#include <inttypes.h>
#include "led.h"
// function to initialize UART
void uart_init (void)
{
UBRRH=(BAUDRATE>>8);
UBRRL=BAUDRATE; //set baud rate
UCSRB|=(1<<TXEN)|(1<<RXEN); //enable receiver and transmitter
UCSRC|=(1<<URSEL)|(1<<UCSZ0)|(1<<UCSZ1);// 8bit data format
}
// function to send data
void uart_transmit (unsigned char data)
{
while (!( UCSRA & (1<<UDRE))); // wait while register is free
UDR = data; // load data in the register
}
// function to receive data
unsigned char uart_receive (void)
{
while(!(UCSRA) & (1<<RXC)); // wait while data is being received
return UDR; // return 8-bit data
}
// main function: entry point of program
int main (void)
{
unsigned char a = 0;
char buffer[10] = 0;
DDRB = 0xFF;
uart_init(); // initialize UART
while(1)
{
a=uart_receive(); // save the received data in a variable
uart_transmit(a); // send it back
blink(a - 0); // print in the led
_delay_ms(100); // wait before next attempt
}
return 0;
}
The problem I am facing is that none of the registers related to the USART seem to be recognized by the compiler. See an example of the compilation error I am getting:
'UBRRH' undeclared (first use in this function)
Am I missing an include here?
It seems that code you have is not for ATMEGA168, the errors you are getting are due to some registers that doesnt exist in ATMEGA168. In ATMEGA168, there is more than one UART, so the register names are numbered. You can use UBRR0H instead of UBRRH, for example.
Try this:
#ifdef UDR0
#define UBRRH UBRR0H
#define UBRRL UBRR0L
#define UDR UDR0
#define UCSRA UCSR0A
#define UDRE UDRE0
#define RXC RXC0
#define UCSRB UCSR0B
#define RXEN RXEN0
#define TXEN TXEN0
#define RXCIE RXCIE0
#define UCSRC UCSR0C
#define URSEL
#define UCSZ0 UCSZ00
#define UCSZ1 UCSZ01
#define UCSRC_SELECT 0
#else
#define UCSRC_SELECT (1 << URSEL)
#endif
#define BAUD 9600UL
#define UBRRVAL (F_CPU/(BAUD*16)-1)
#define USE_SLEEP 1
void uart_init() {
/* set baud rate */
UBRRH = UBRRVAL >> 8;
UBRRL = UBRRVAL & 0xff;
/* set frame format: 8 bit, no parity, 1 bit */
UCSRC = UCSRC_SELECT | (1 << UCSZ1) | (1 << UCSZ0);
/* enable serial receiver and transmitter */
#if !USE_SLEEP
UCSRB = (1 << RXEN) | (1 << TXEN);
#else
UCSRB = (1 << RXEN) | (1 << TXEN) | (1 << RXCIE);
#endif
}
void uart_putc(uint8_t c) {
if(c == '\n')
uart_putc('\r');
/* wait until transmit buffer is empty */
while(!(UCSRA & (1 << UDRE)));
/* send next byte */
UDR = c;
}
uint8_t uart_getc()
{
/* wait until receive buffer is full */
#if USE_SLEEP
uint8_t sreg = SREG;
sei();
while(!(UCSRA & (1 << RXC)))
sleep_mode();
SREG = sreg;
#else
while(!(UCSRA & (1 << RXC)));
#endif
uint8_t b = UDR;
if(b == '\r')
b = '\n';
return b;
}
int main(){
DDRB = 0xff;
uint8_t data = 0;
uart_init();
while(1){
data = uart_getc();
uart_putc(data);
blink(a - 0);
_delay_ms(100);
}
return 0;
}

Undefined reference to `usbInit' in C AVR

I use v-usb library for my project.
I wrote code and i want compile it, but unfortunately I have an error which I'm unable to resolve.
Here is my screen-shot:
Description Resource Path Location Type
make: *** [USB_module.elf] Error 1 USB_module C/C++ Problem
undefined reference to `usbInit' main.c /USB_module C/C++ Problem
undefined reference to `usbMsgPtr' main.c /USB_module C/C++ Problem
undefined reference to `usbPoll' main.c /USB_module C/C++ Problem
This situation is for me strange because i have in header this:
#include "usbconfig.h"
#include "usbdrv/usbdrv.h"
#include "usbdrv/oddebug.h"
And usbdrv/usbdrv.h defines the USBpoll function:
Shouldn't the compiler be able to compile it?
Here is my project: http://goo.gl/P6ujK
And here is my entire workspace directory: http://minus.com/mbhTkJuvOK#1
Here is my code: main.c:
/*
* main.c
*
* Created on: 25-01-2012
* Author: Bordeux
*/
#define F_CPU 12000000
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <avr/wdt.h>
#include "usbconfig.h"
#include "usbdrv/usbdrv.h"
#include "usbdrv/oddebug.h"
#define DDS1_SDA (1<<1) //PORTB1
#define DDS_SCL (1<<3) //PORTB3
#define DDS_UPDATE (1<<4) //PORTB4
static uchar usb_val;
USB_PUBLIC uchar usbFunctionWrite(uchar *data, uchar len) //sends len bytes to DDS_SDA
{
uchar i;
uchar b;
uchar adr=0;
while (len!=0)
{
b=1;
for (i=0; i<8; i++)
{
if (b & data[adr])
{
PORTB = (PORTB | DDS1_SDA) & ~DDS_SCL;
PORTB = PORTB | DDS_SCL;
}
else
{
PORTB = PORTB & (~DDS1_SDA & ~DDS_SCL);
PORTB = PORTB | DDS_SCL;
}
b=b<<1;
}
len--;
adr++;
}
if (usb_val)
{
PORTB = PORTB | DDS_UPDATE;// update DDS
PORTB = PORTB & ~DDS_UPDATE;
}
return 1;
}
USB_PUBLIC uchar usbFunctionSetup(uchar data[8])
{
usbRequest_t *rq = (void *)data;
static uchar replyBuf[3];
usbMsgPtr = replyBuf;
if(rq->bRequest == 0) // ECHO value
{
replyBuf[0] = data[2]; // rq->bRequest identical data[1]!
replyBuf[1] = data[3];
return 2;
}
if(rq->bRequest == 1) // set port directions
{
// DDRA = data[2];
DDRB = data[3];
DDRD = data[4] & (~USBMASK & ~(1 << 2)); // protect USB interface
return 0;
}
if(rq->bRequest == 2) // read ports
{
// replyBuf[0] = PINA;
replyBuf[1] = PINB;
replyBuf[2] = PIND;
return 3;
}
if(rq->bRequest == 3) // read port states
{
// replyBuf[0] = PORTA;
replyBuf[1] = PORTB;
replyBuf[2] = PORTD;
return 3;
}
if(rq->bRequest == 4) // set ports
{
// PORTA = data[2];
PORTB = data[3];
PORTD = data[4];
return 0;
}
if(rq->bRequest == 5) // use usbFunctionWrite to transfer len bytes to DDS
{
usb_val = data[2]; // usb_val!=0 => DDS update pulse after data transfer
return 0xff;
}
if(rq->bRequest == 6)
{
PORTB = PORTB | DDS_UPDATE; // issue update pulse to DDS
PORTB = PORTB & ~DDS_UPDATE;
return 0;
}
replyBuf[0] = 0xff; // return value 0xff => command not supported
return 1;
}
int main(void)
{
wdt_enable(WDTO_1S); // set Watchdog Timer
odDebugInit();
PORTB=0xe0; // Set PortB 0-4 zero
DDRB=0x1f; // Set PORTB 0-4 output
PORTD = 0; /* no pullups on USB pins */
DDRD = ~USBMASK & ~(1 << 2); /* all outputs except USB data and PD2 = INT0 */
usbInit();
sei();
for(;;) /* main event loop */
{
wdt_reset(); // restart watchdog timer
usbPoll();
}
return 0;
}
solution:
mv usbdrv.c usbdrv.cpp
or compile with avr-g++
You need to link against whatever file supplies usbInit etc., from the looks of your screen shots you've shown the file usbdrv.c, but not actually compiled/linked it into your project. Only usbdrv.h is showing in the tree view.
#includeing the header file shows the compiler the declaration of the function, you need to make sure it sees the definition somewhere too.
you could also have included usbdrv.h in extern "C":
extern "C" {
#include "usbdrv.h";
}

Resources