bianchi77
Advanced Member level 4
- Joined
- Jun 11, 2009
- Messages
- 1,313
- Helped
- 21
- Reputation
- 44
- Reaction score
- 20
- Trophy points
- 1,318
- Location
- California
- Activity points
- 9,442
lcd_cmd()
{
PORTD = 0xFF;
_delay_ms(100);
PORTD = 0x00;
_delay_ms(100);
en=0;
_delay_ms(100);
en=1;
_delay_ms(100);
rs=0;
_delay_ms(100);
rs=1;
_delay_ms(100);
rw=0;
_delay_ms(100);
rw=1;
_delay_ms(100);
}
main()
{
lcd_cmd();
}
lcd_cmd(unsigned char data_cmd)
{
PORTD = data_cmd;
_delay_ms(100);
PORTD = data_cmd;
_delay_ms(100);
en=0;
_delay_ms(100);
en=1;
_delay_ms(100);
rs=0;
_delay_ms(100);
rs=1;
_delay_ms(100);
rw=0;
_delay_ms(100);
rw=1;
_delay_ms(100);
}
main()
{
while(1)
{
lcd_cmd(0xFF);
_delay_ms(100);
lcd_cmd(0x00);
}
}
How do I pass an IO port as a parameter to a function?
Consider this example code:
#include <inttypes.h>
#include <avr/io.h>
void
set_bits_func_wrong (volatile uint8_t port, uint8_t mask)
{
port |= mask;
}
void
set_bits_func_correct (volatile uint8_t *port, uint8_t mask)
{
*port |= mask;
}
#define set_bits_macro(port,mask) ((port) |= (mask))
int main (void)
{
set_bits_func_wrong (PORTB, 0xaa);
set_bits_func_correct (&PORTB, 0x55);
set_bits_macro (PORTB, 0xf0);
return (0);
}
The first function will generate object code which is not even close to what is intended. The major problem arises when the function is called. When the compiler sees this call, it will actually pass the value of the PORTB register (using an IN instruction), instead of passing the address of PORTB (e.g. memory mapped io addr of 0x38, io port 0x18 for the mega128). This is seen clearly when looking at the disassembly of the call:
set_bits_func_wrong (PORTB, 0xaa);
10a: 6a ea ldi r22, 0xAA ; 170
10c: 88 b3 in r24, 0x18 ; 24
10e: 0e 94 65 00 call 0xca
So, the function, once called, only sees the value of the port register and knows nothing about which port it came from. At this point, whatever object code is generated for the function by the compiler is irrelevant. The interested reader can examine the full disassembly to see that the function's body is completely fubar.
The second function shows how to pass (by reference) the memory mapped address of the io port to the function so that you can read and write to it in the function. Here's the object code generated for the function call:
set_bits_func_correct (&PORTB, 0x55);
112: 65 e5 ldi r22, 0x55 ; 85
114: 88 e3 ldi r24, 0x38 ; 56
116: 90 e0 ldi r25, 0x00 ; 0
118: 0e 94 7c 00 call 0xf8
You can clearly see that 0x0038 is correctly passed for the address of the io port. Looking at the disassembled object code for the body of the function, we can see that the function is indeed performing the operation we intended:
void
set_bits_func_correct (volatile uint8_t *port, uint8_t mask)
{
f8: fc 01 movw r30, r24
*port |= mask;
fa: 80 81 ld r24, Z
fc: 86 2b or r24, r22
fe: 80 83 st Z, r24
}
100: 08 95 ret
Notice that we are accessing the io port via the LD and ST instructions.
The port parameter must be volatile to avoid a compiler warning.
Note:
Because of the nature of the IN and OUT assembly instructions, they can not be used inside the function when passing the port in this way. Readers interested in the details should consult the Instruction Set data sheet.
Finally we come to the macro version of the operation. In this contrived example, the macro is the most efficient method with respect to both execution speed and code size:
set_bits_macro (PORTB, 0xf0);
11c: 88 b3 in r24, 0x18 ; 24
11e: 80 6f ori r24, 0xF0 ; 240
120: 88 bb out 0x18, r24 ; 24
Of course, in a real application, you might be doing a lot more in your function which uses a passed by reference io port address and thus the use of a function over a macro could save you some code space, but still at a cost of execution speed.
Care should be taken when such an indirect port access is going to one of the 16-bit IO registers where the order of write access is critical (like some timer registers). All versions of avr-gcc up to 3.3 will generate instructions that use the wrong access order in this situation (since with normal memory operands where the order doesn't matter, this sometimes yields shorter code).
See **broken link removed** for a possible workaround.
avr-gcc versions after 3.3 have been fixed in a way where this optimization will be disabled if the respective pointer variable is declared to be volatile, so the correct behaviour for 16-bit IO ports can be forced that way.
yes I'm testing a hardware,Are you testing in hardware? That is are you using hardware logic analyzer and viewing the result in logic analyzer software?
I don't understand my friend.......Are you testing in hardware? That is are you using hardware logic analyzer and viewing the result in logic analyzer software?
I tested it with Proteus Logic Analyzer and I am getting all the signals.
/*
* port.c
*
* Created: 7/05/2013 7:31:27 PM
* Author: Antonius
*/
#include <avr/io.h>
#include <avr/delay.h>
// structure to allow bit field operations, name conversions: PORTA.0 -> PORT_A.b0 PORTB.7 -> PORT_B.b7
typedef struct{
uint8_t b0:1;
uint8_t b1:1;
uint8_t b2:1;
uint8_t b3:1;
uint8_t b4:1;
uint8_t b5:1;
uint8_t b6:1;
uint8_t b7:1;
} bits;
// define all the ports of your microcontroller, add more ports depending on the available mcu ports
#define PORT_A (* (volatile bits *) &PORTA)
#define LCD_data PORTD
#define en PORT_A.b0
#define rs PORT_A.b1
#define rw PORT_A.b2
lcd_cmd()
{
PORTD = 0xFF;
_delay_ms(100);
PORTD = 0x00;
_delay_ms(100);
//PORTD = data_port;
en=0;
_delay_ms(100);
en=1;
_delay_ms(100);
rs=0;
_delay_ms(100);
rs=1;
_delay_ms(100);
rw=0;
_delay_ms(100);
rw=1;
_delay_ms(100);
}
int main(void)
{
DDRD = 0xFF;
DDRA = 0xFF;
while(1)
{
lcd_cmd();
/*
PORTD = 0xFF;
_delay_ms(100);
PORTD = 0x00;
_delay_ms(100);
en=0;
_delay_ms(100);
en=1;
_delay_ms(100);
rs=0;
_delay_ms(100);
rs=1;
_delay_ms(100);
rw=0;
_delay_ms(100);
rw=1;
_delay_ms(100);
*/
}
}
/*
* port.c
*
* Created: 7/05/2013 7:31:27 PM
* Author: Antonius
*/
#include <avr/io.h>
#include <avr/delay.h>
// structure to allow bit field operations, name conversions: PORTA.0 -> PORT_A.b0 PORTB.7 -> PORT_B.b7
typedef struct{
uint8_t b0:1;
uint8_t b1:1;
uint8_t b2:1;
uint8_t b3:1;
uint8_t b4:1;
uint8_t b5:1;
uint8_t b6:1;
uint8_t b7:1;
} bits;
// define all the ports of your microcontroller, add more ports depending on the available mcu ports
#define PORT_A (* (volatile bits *) &PORTA)
#define LCD_data PORTD
#define en PORT_A.b0
#define rs PORT_A.b1
#define rw PORT_A.b2
lcd_cmd()
{
PORTA = 0xFF;
_delay_ms(100);
PORTA = 0x00;
_delay_ms(100);
//PORTD = data_port;
/*
en=0;
_delay_ms(100);
en=1;
_delay_ms(100);
rs=0;
_delay_ms(100);
rs=1;
_delay_ms(100);
rw=0;
_delay_ms(100);
rw=1;
_delay_ms(100);
*/
}
int main(void)
{
DDRD = 0xFF;
DDRA = 0xFF;
while(1)
{
lcd_cmd();
/*
PORTD = 0xFF;
_delay_ms(100);
PORTD = 0x00;
_delay_ms(100);
en=0;
_delay_ms(100);
en=1;
_delay_ms(100);
rs=0;
_delay_ms(100);
rs=1;
_delay_ms(100);
rw=0;
_delay_ms(100);
rw=1;
_delay_ms(100);
*/
}
}
Finally you are getting the outputs on all pins.
#include <avr/io.h>
#include <util/delay.h>
//Mention Clock frequency here
#define _XTAL_FREQ 8000000
// structure to allow bit field operations, name conversions: PORTA.0 -> PORT_A.b0 PORTB.7 -> PORT_B.b7
typedef struct{ uint8_t b0:1;
uint8_t b1:1;
uint8_t b2:1;
uint8_t b3:1;
uint8_t b4:1;
uint8_t b5:1;
uint8_t b6:1;
uint8_t b7:1; } bits;
// define all the ports of your microcontroller, add more ports depending on the available mcu ports
#define PORT_A (* (volatile bits *) &PORTA)
#define PIN_A (* (volatile bits *) &PINA)
#define DDR_A (* (volatile bits *) &DDRA)
#define PORT_B (* (volatile bits *) &PORTB)
#define PIN_B (* (volatile bits *) &PINB)
#define DDR_B (* (volatile bits *) &DDRB)
#define lcd_data_pin PORTD
#define en PORT_A.b0
#define rs PORT_A.b1
//#define rw PORT_A.b2
void lcd_init();
void lcd_data(unsigned char data1);
void lcd_cmd(unsigned char cmd);
void lcd_control(unsigned char cmdordata);
void lcd_string(unsigned char *str);
void lcd_init(){
lcd_cmd(0x38);
_delay_ms(500);
lcd_cmd(0x0E);
_delay_ms(500);
lcd_cmd(0x01);
_delay_ms(500);
lcd_cmd(0x06);
_delay_ms(500);
lcd_cmd(0x0C);
_delay_ms(500);
lcd_cmd(0x80);
}
void lcd_data(unsigned char data1)
{
lcd_data_pin = data1;
lcd_control(2);
}
void lcd_cmd(unsigned char cmd){
lcd_data_pin = cmd;
lcd_control(1);
}
void lcd_control(unsigned char cmdordata){
if(cmdordata == 1){
rs=0;
//rw=0;
en=1;
_delay_ms(150);
en=0;
}
else if(cmdordata == 2){
rs=1;
//rw=0;
en=1;
_delay_ms(150);
en=0;
}
}
void lcd_string(unsigned char *str){
while(*str){
lcd_data(*str++);
}
}
unsigned char msg[20] = "Working?";
int main(){
DDRA = 0xFF;
DDRD = 0xFF;
PORTA = 0x00;
PORTD = 0x00;
lcd_init();
while(1){
lcd_cmd(0x01);
lcd_cmd(0x80);
lcd_data('A');
lcd_cmd(0xC0);
lcd_string(msg);
}
return (0);
}
test_port()
{
rs=0;
_delay_ms(100);
rs=1;
en=0;
_delay_ms(100);
en=1;
_delay_ms(100);
lcd_data_pin = 0xFF;
_delay_ms(100);
lcd_data_pin = 0x00;
_delay_ms(100);
}
while(1){
lcd_cmd(0x38);
}
void lcd_cmd(unsigned char cmd){
lcd_data_pin = cmd;
//lcd_control(1);
}
main()
{
while(1){
lcd_cmd(0x38);
_delay_ms(100);
lcd_cmd(0x00);
}
/*
* LCD_8bit.c
*
* Created: 9/05/2013 8:53:29 AM
* Author: Antonius
*/
/* Simple LCD character display module demonstrator using
* the 8-bit interface. No handling of the busy flag is
* done - all timing contraints are handled by delay loops.
* This code should be good to run at up to 8 MHz.
* Above that you might have to tweak the timing of things
* including, but not restricted to, the existing delays.
*/
#include <avr/io.h>
#include <util/delay.h>
/* Here are some defines for the data connections,
* DB0..7 on the LCD display module. These should be wired
* up to the eight bits of any port A..D. You need to alter
* these to fit your wire up of your display.
*/
#define LCD_DATA_PORT PORTD
#define LCD_DATA_DDR DDRD
/* Here are some defines for the control connections
* (RS, R/W and E on the LCD display module). These can be wired
* to any pins on any port A..D (all to the same port though).
* You need to alter these to fit your wire up of your display.
*/
#define LCD_CTRL_PORT PORTA
#define LCD_CTRL_DDR DDRA
#define LCD_RS 0
#define LCD_RW 1
#define LCD_E 2
/*
* YOU SHOULD NOT NEED TO ALTER ANYTHING BEYOND THIS POINT!
*/
/* Here are some defines for the LCD instructions we'll use.
*/
#define LCD_FUNCTION_SET 0x38 // 0b00111000
#define LCD_DISPLAY_OFF 0x08 // 0b00001000
#define LCD_DISPLAY_ON 0x0F // 0b00001111
#define LCD_DISPLAY_CLEAR 0x01 // 0b00000001
#define LCD_ENTRY_MODE_SET 0x06 // 0b00000110
#define LCD_CURSOR_HOME 0x02 // 0b00000010
#define LCD_
/* LcdSendByte
*
* Sends a 8-bit byte to the display.
*
* Parameters:
* uint8_t theByte The byte to send to the display
*
* Returns:
* nothing
*/
void LcdSendByte(uint8_t theByte)
{
// Short delay needed here...
_delay_us(50);
// Output the byte
LCD_DATA_PORT = theByte;
// Toggle the E line
LCD_CTRL_PORT |= (1<<LCD_E); // Going up..
// Short delay needed here...
_delay_us(50);
LCD_CTRL_PORT &= ~(1<<LCD_E); // ..and down.
}
/* LcdSendInstruction
*
* Sends an instruction to the display.
*
* Parameters:
* uint8_t command This byte is sent to the display as
* an instruction (RS low).
* Returns:
* nothing
*/
void LcdSendInstruction(uint8_t theInstruction)
{
// RS low
LCD_CTRL_PORT &= ~(1<<LCD_RS);
// Send it
LcdSendByte(theInstruction);
}
/* LcdSendCharacter
*
* Sends a character to the display.
*
* Parameters:
* uint8_t nibble This byte is sent to the display as
* a character (RS high).
* Returns:
* nothing
*/
void LcdSendCharacter( uint8_t theChar )
{
// RS high
LCD_CTRL_PORT |= (1<<LCD_RS);
// Send it
LcdSendByte(theChar);
}
void LcdInitialize(void)
{
// initialize LCD control lines
LCD_CTRL_PORT &= ~(1<<LCD_RS);
LCD_CTRL_PORT &= ~(1<<LCD_RW);
LCD_CTRL_PORT &= ~(1<<LCD_E);
// initialize LCD control lines to output
LCD_CTRL_DDR |= (1<<LCD_RS);
LCD_CTRL_DDR |= (1<<LCD_RW);
LCD_CTRL_DDR |= (1<<LCD_E);
// initialize LCD data port to output
LCD_DATA_DDR = 0xFF;
// First part of init sequence is 3 x Function Set with
// stipulated waits (no Busy Flag available).
_delay_ms(15);
LcdSendInstruction( LCD_FUNCTION_SET );
_delay_ms(5);
LcdSendInstruction( LCD_FUNCTION_SET );
_delay_us(100);
LcdSendInstruction( LCD_FUNCTION_SET );
_delay_ms(5);
// We are now in 8-bit mode, and the busy flag is available.
// Do the rest of the init sequence.
LcdSendInstruction( LCD_FUNCTION_SET );
LcdSendInstruction( LCD_DISPLAY_OFF );
LcdSendInstruction( LCD_DISPLAY_CLEAR );
_delay_ms(5);
LcdSendInstruction( LCD_ENTRY_MODE_SET );
LcdSendInstruction( LCD_DISPLAY_ON );
}
char message[] = "8-bit avr-gcc";
int main(void)
{
LcdInitialize();
volatile int i = 0;
while (message[i] != 0)
{
LcdSendCharacter(message[i]);
i++;
}
while(1);
return 0;
}
AVcc is for ADC. Don't connect it to Vcc.
#include <avr/io.h>
#include <util/delay.h>
// structure to allow bit field operations, name conversions: PORTA.0 -> PORT_A.b0 PORTB.7 -> PORT_B.b7
typedef struct{ uint8_t b0:1;
uint8_t b1:1;
uint8_t b2:1;
uint8_t b3:1;
uint8_t b4:1;
uint8_t b5:1;
uint8_t b6:1;
uint8_t b7:1; } bits;
// define all the ports of your microcontroller, add more ports depending on the available mcu ports
#define PORT_A (* (volatile bits *) &PORTA)
#define PIN_A (* (volatile bits *) &PINA)
#define DDR_A (* (volatile bits *) &DDRA)
#define PORT_B (* (volatile bits *) &PORTB)
#define PIN_B (* (volatile bits *) &PINB)
#define DDR_B (* (volatile bits *) &DDRB)
//Mention Clock frequency here
#define _XTAL_FREQ 8000000
#define lcd_data_pin PORTD
#define en PORT_A.b0
#define rs PORT_A.b1
#define rw PORT_A.b2
void lcd_init();
void lcd_data(unsigned char data1);
void lcd_cmd(unsigned char cmd);
void lcd_control(unsigned char cmdordata);
void lcd_string(unsigned char *str);
void lcd_init(){
lcd_cmd(0x02);
lcd_cmd(0x28);
lcd_cmd(0x0C);
lcd_cmd(0x06);
lcd_cmd(0x80);
}
void lcd_data(unsigned char data1)
{
DDRD = 0xFF;
lcd_data_pin = data1;// & 0x0F;
lcd_control(2);
/*
lcd_data_pin = (data1>> 4) & 0x0F;
lcd_control(2);
*/
}
void lcd_cmd(unsigned char cmd){
DDRD = 0xFF;
lcd_data_pin = cmd ;//& 0x0F;
lcd_control(1);
/*
lcd_data_pin = (cmd >> 4) & 0x0F;
lcd_control(1);
*/
}
void lcd_control(unsigned char cmdordata){
if(cmdordata == 1){
en=1;
rs=0;
rw=0;
_delay_ms(1);
en=0;
}
else if(cmdordata == 2){
en=1;
rs=1;
rw=0;
_delay_ms(1);
en=0;
}
}
void lcd_string(unsigned char *str){
while(*str){
lcd_data(*str++);
}
}
int main(){
DDRA = 0xFF;
//lcd_init();
//lcd_data('A');
while(1){
//lcd_cmd(0xFF);
//_delay_ms(50);
//lcd_cmd(0x00);
_delay_ms(50);
lcd_init();
//lcd_string("Working?");
}
return (0);
}
#include <avr/io.h>
#include <util/delay.h>
// structure to allow bit field operations, name conversions: PORTA.0 -> PORT_A.b0 PORTB.7 -> PORT_B.b7
typedef struct{ uint8_t b0:1;
uint8_t b1:1;
uint8_t b2:1;
uint8_t b3:1;
uint8_t b4:1;
uint8_t b5:1;
uint8_t b6:1;
uint8_t b7:1; } bits;
// define all the ports of your microcontroller, add more ports depending on the available mcu ports
#define PORT_A (* (volatile bits *) &PORTA)
#define PIN_A (* (volatile bits *) &PINA)
#define DDR_A (* (volatile bits *) &DDRA)
#define PORT_B (* (volatile bits *) &PORTB)
#define PIN_B (* (volatile bits *) &PINB)
#define DDR_B (* (volatile bits *) &DDRB)
//Mention Clock frequency here
#define _XTAL_FREQ 8000000
#define lcd_data_pin PORTD
#define en PORT_A.b0
#define rs PORT_A.b1
#define rw PORT_A.b2
void lcd_init();
void lcd_data(unsigned char data1);
void lcd_cmd(unsigned char cmd);
void lcd_control(unsigned char cmdordata);
void lcd_string(unsigned char *str);
void lcd_init(){
/*
lcd_cmd(0x02);
lcd_cmd(0x28);
lcd_cmd(0x0C);
lcd_cmd(0x06);
lcd_cmd(0x80);
*/
lcd_data_pin = 0x02;
_delay_ms(50);
lcd_data_pin = 0x28;
_delay_ms(50);
lcd_data_pin = 0x0C;
_delay_ms(50);
lcd_data_pin = 0x06;
_delay_ms(50);
lcd_data_pin = 0x80;
_delay_ms(50);
}
void lcd_data(unsigned char data1)
{
lcd_data_pin = data1;// & 0x0F;
lcd_control(2);
/*
lcd_data_pin = (data1>> 4) & 0x0F;
lcd_control(2);
*/
}
void lcd_cmd(unsigned char cmd){
DDRD = 0xFF;
lcd_data_pin = cmd ;//& 0x0F;
//lcd_control(1);
/*
lcd_data_pin = (cmd >> 4) & 0x0F;
lcd_control(1);
*/
}
void lcd_control(unsigned char cmdordata){
if(cmdordata == 1){
en=1;
rs=0;
rw=0;
_delay_ms(1);
en=0;
}
else if(cmdordata == 2){
en=1;
rs=1;
rw=0;
_delay_ms(1);
en=0;
}
}
void lcd_string(unsigned char *str){
while(*str){
lcd_data(*str++);
}
}
int main(){
DDRA = 0xFF;
DDRD = 0xFF;
//lcd_init();
//lcd_data('A');
while(1){
//lcd_cmd(0xFF);
//_delay_ms(50);
//lcd_cmd(0x00);
_delay_ms(50);
lcd_init();
//lcd_string("Working?");
}
return (0);
}
how can I change the configuration of ATMEGA128 ? is it related with fuse bit ?Test with another ATMega128 or test the circuit with ATMega16. If it works then problem is ATMega128 or configuration of ATMega128.
Yes. Test with ATMega32.
That's exactly the issue I have here.....could it be configuration on ATMEGA128 ???? weird...I tested on ATMEGA32, the code runs allright.....hi Guys,
I am also facing the same problem in my LCD code movement I invoke the function in the code the portA blink stops but as soon as I comment the init_lCD code it works....is this is typical issue with ATMEGA128 board.....how ever my port pin for LCD data lines are PORTC and Control lines are PORTG pin 0,1,2.... I am wondering is there is missing too.....
Good Luck
- - - Updated - - -
hi Guys,
I am also facing the same problem in my LCD code movement I invoke the function in the code the portA blink stops but as soon as I comment the init_lCD code it works....is this is typical issue with ATMEGA128 board.....how ever my port pin for LCD data lines are PORTC and Control lines are PORTG pin 0,1,2.... I am wondering is there is missing too.....
Good Luck
#include <avr/io.h>
#include <util/delay.h>
// structure to allow bit field operations, name conversions: PORTA.0 -> PORT_A.b0 PORTB.7 -> PORT_B.b7
typedef struct{ uint8_t b0:1;
uint8_t b1:1;
uint8_t b2:1;
uint8_t b3:1;
uint8_t b4:1;
uint8_t b5:1;
uint8_t b6:1;
uint8_t b7:1; } bits;
// define all the ports of your microcontroller, add more ports depending on the available mcu ports
#define PORT_D (* (volatile bits *) &PORTD)
#define PIN_D (* (volatile bits *) &PIND)
#define DDR_D (* (volatile bits *) &DDRD)
#define PORT_G (* (volatile bits *) &PORTG)
#define PIN_G (* (volatile bits *) &PING)
#define DDR_G (* (volatile bits *) &DDRG)
//Mention Clock frequency here
//#define _XTAL_FREQ 8000000
#define lcd_data_pin PORTA
#define en PORT_D.b0
#define rs PORT_D.b1
#define rw PORT_D.b2
void lcd_init();
void lcd_data(unsigned char data1);
void lcd_cmd(unsigned char cmd);
void lcd_control(unsigned char cmdordata);
void lcd_string(unsigned char *str);
void lcd_init(){
lcd_cmd(0x30);
_delay_ms(100);
lcd_cmd(0x38);
_delay_ms(100);
lcd_cmd(0x0F);
_delay_ms(100);
lcd_cmd(0x80);
_delay_ms(100);
}
void lcd_data(unsigned char data1)
{
lcd_data_pin = data1;// & 0x0F;
en=1;
rs=1;
rw=0;
_delay_ms(10);
en=0;
}
void lcd_cmd(unsigned char cmd){
lcd_data_pin = cmd ;
en=1;
rs=0;
rw=0;
_delay_ms(10);
en=0;
}
void lcd_string(unsigned char *str){
while(*str){
lcd_data(*str++);
}
}
int main(){
DDR_D.b0 = 1;
DDR_D.b1 = 1;
DDR_D.b2 = 1;
DDRA = 0xFF;
lcd_init();
while(1){
_delay_ms (200);
lcd_cmd(0x80);//put the cursor into the first row
_delay_ms (300);
lcd_cmd(0x01);//Clear display
_delay_ms (300);
lcd_cmd(0xC0);//goto second row
_delay_ms (300);
lcd_cmd(0x01); //Clear display
lcd_string("HELLO ATMEGA32");
}
return (0);
}
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?