9/11 USART

정유석·2024년 9월 11일
post-thumbnail

클락으로 나눴을 경우
I2C, SPI 클락이 있는 동기 통신
UART 비동기 통신, USART는 Synchro; 동기 통신

전이중, 반이중 방식으로 나눴을 경우
1:1, 1:N 방식으로 나눴을 경우

USART

데이터 시트 20 또는 25

#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>

void UART0_Init();
void UART0_Transmit(char data);
unsigned UART0_Recevie();

int main(void)
{
	UART0_Init();
	
    while (1) 
    {
		UART0_Transmit(UART0_Recevie());
    }
}

//9600 bps 설정
//2배속 모드
//비동기, 8비트 데이터, 패리티비트 없음, 스톱비트 1bit
void UART0_Init()
{
	UBRR0H = 0;
	UBRR0L = 207; //9600bps
	
	UCSR0A |= (1<<U2X0); //2배속
	//UCSR0C |= 0x06; //비동기, 8비트 데이터, 패리티비트 없음, 스톱비트 1bit
	//기본 세팅값이 0000_0110임
	
	UCSR0B |= (1<<RXEN0); //수신 가능
	UCSR0B |= (1<<TXEN0); //송신 가능
}
void UART0_Transmit(char data)
{
	while(!(UCSR0A & (1<<UDRE0))); //송신가능?, UDR 비어있는지?, 비어있으면 1로 됨 !연산을 통해 while 빠져나옴
	UDR0 = data;
}
unsigned UART0_Recevie()
{
	while(!(UCSR0A & (1<<RXC0))); //수신대기
	return UDR0;
}

led 켜기

#include "uart0.h"



int main(void)
{
	DDRB = 0xff;
	PORTB = 0x00;
	
	UART0_Init();
	
    while (1) 
    {
		//UART0_Transmit(UART0_Recevie());
		//char led = UART0_Recevie();
		if (UART0_Recevie() == 'a')
		{
			PORTB = 0xff;
		}
		else if (UART0_Recevie() == 'b')
		{
			PORTB = 0x00;
		}
    }
}

문자 'a'를 보내면 led 켜짐, 문자 'b를 보내면 led 꺼짐

인터럽트

main.c

#include "uart0.h"

//출력 스트림 <stdio.h>안에있음, 표준
FILE OUTPUT = FDEV_SETUP_STREAM(UART0_Transmit, NULL, _FDEV_SETUP_WRITE);

char rxBuff[100] = {0}; //수신버퍼, 초기화
uint8_t rxFlag = 0; //수신 완료 플래그

ISR(USART0_RX_vect) //Rx 인터럽트가 발생되면 ISR함수 호출
{
	static uint8_t rxHead = 0; //수신된 데이터 인텍스
	uint8_t rxData = UDR0;
	
	if(rxData == '\n' || rxData == '\r') //수신데이터가 개행, 리턴이면
	{
		rxBuff[rxHead] = '\0'; //널 추가
		rxHead = 0;
		rxFlag = 1;
	}
	else
	{
		rxBuff[rxHead] = rxData;
		rxHead++;
	}
}

int main(void)
{
    UART0_Init();
	uint8_t rxData;
	stdout = &OUTPUT;
	
	sei();
	
    while (1) 
    {
		if(rxFlag == 1)
		{
			rxFlag = 0;
			printf(rxBuff);
		}
    }
}

uart0.c

#include "uart0.h"

//9600 bps 설정
//2배속 모드
//비동기, 8비트 데이터, 패리티비트 없음, 스톱비트 1bit
//수신 인터럽트 활성화
void UART0_Init()
{
	UBRR0H = 0;
	UBRR0L = 207; //9600bps
	
	UCSR0A |= (1<<U2X0); //2배속
	//UCSR0C |= 0x06; //비동기, 8비트 데이터, 패리티비트 없음, 스톱비트 1bit
	//기본 세팅값이 0000_0110임
	
	UCSR0B |= (1<<RXEN0); //수신 가능
	UCSR0B |= (1<<TXEN0); //송신 가능
	
	UCSR0B |= (1<<RXCIE0); //수신 인터럽트 활성화
}
void UART0_Transmit(char data)
{
	while(!(UCSR0A & (1<<UDRE0))); //송신가능?, UDR 비어있는지?, 비어있으면 1로 됨 !연산을 통해 while 빠져나옴
	UDR0 = data;
}
unsigned UART0_Recevie()
{
	while(!(UCSR0A & (1<<RXC0))); //수신대기
	return UDR0;
}

uart0.h



#ifndef UART0_H_
#define UART0_H_

#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdio.h>

void UART0_Init();
void UART0_Transmit(char data);
unsigned UART0_Recevie();




#endif /* UART0_H_ */

초음파

타이머 카운터 레지스터

main.c

#include "uart0.h"

FILE OUTPUT = FDEV_SETUP_STREAM(UART0_Transmit, NULL, _FDEV_SETUP_WRITE);

void timerInit() 
{
	TCCR1B |= (1<<CS12) | (1<<CS10); //16비트 타이머 1번, 분주비 1024설정
}

void triggerPin()
{
	PORTD &= ~(1<<PORTD1); //LOW
	_delay_us(1);
	PORTD |= (1<<PORTD1); //HIGH
	_delay_us(10);
	PORTD &= ~(1<<PORTD1); //LOW
}

uint8_t meanDistance() //거리측정
{
	TCNT1 = 0;
	while(!(PIND & 0x01)) //echo pin이 HIGH까지 대기
	{
		if(TCNT1 > 65000)
		{
			return;
		}
	}
	TCNT1 = 0;
	while(PIND & 0x01) //echo pin이 LOW까지 대기
	{
		if(TCNT1 > 65000)
		{
			TCNT1 = 0;
			break;
		}
	}
	double pluseWidth = 1000000.0 * TCNT1 * 1024 / 16000000;
	// TCNT1의 값이 us단위임, us를 s단위로 바꿔주기 위해 1000000.0 곱함
	// 거리 = 시간 * 속도 (속도 : 340m/sec)
	
	return pluseWidth / 58;
}


int main(void)
{
	uint8_t distance;
	
	stdout = &OUTPUT;
	
	UART0_Init();
	
	sei();
	
	DDRD |= 0x02;
	DDRD &= 0xfe;
	
	timerInit();
	
    while (1) 
    {
		triggerPin();
		distance = meanDistance();
		printf("Distance : %d cm\r\n", distance);
		_delay_ms(1000);
    }
}

uart0.c

#include "uart0.h"

//9600 bps 설정
//2배속 모드
//비동기, 8비트 데이터, 패리티비트 없음, 스톱비트 1bit
//수신 인터럽트 활성화
void UART0_Init()
{
	UBRR0H = 0;
	UBRR0L = 207; //9600bps
	
	UCSR0A |= (1<<U2X0); //2배속
	//UCSR0C |= 0x06; //비동기, 8비트 데이터, 패리티비트 없음, 스톱비트 1bit
	//기본 세팅값이 0000_0110임
	
	UCSR0B |= (1<<RXEN0); //수신 가능
	UCSR0B |= (1<<TXEN0); //송신 가능
	
	UCSR0B |= (1<<RXCIE0); //수신 인터럽트 활성화
}
void UART0_Transmit(char data)
{
	while(!(UCSR0A & (1<<UDRE0))); //송신가능?, UDR 비어있는지?, 비어있으면 1로 됨 !연산을 통해 while 빠져나옴
	UDR0 = data;
}
unsigned UART0_Recevie()
{
	while(!(UCSR0A & (1<<RXC0))); //수신대기
	return UDR0;
}

uart0.h

#ifndef UART0_H_
#define UART0_H_

#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdio.h>

void UART0_Init();
void UART0_Transmit(char data);
unsigned UART0_Recevie();




#endif /* UART0_H_ */

LCD에 초음파 거리 표시

#include "uart0.h"
#include "sonic.h"
#include "I2C.h"
#include "I2C_LCD.h"

FILE OUTPUT = FDEV_SETUP_STREAM(UART0_Transmit, NULL, _FDEV_SETUP_WRITE);

int main(void)
{
	uint8_t distance;
	
	stdout = &OUTPUT;
	
	UART0_Init();
	
	sei();
	
	DDRD |= 0x08;
	DDRD &= 0xef;
	
	timerInit();
	
	uint8_t buff[30];
	
	LCD_Init();
	LCD_WriteStringXY(0,0,"Hello ATmega128a");
	
    while (1) 
    {
		triggerPin();
		distance = meanDistance();
    
		sprintf(buff, "distance : %-5d", distance);
		LCD_WriteStringXY(1,0,buff);
		_delay_ms(1000);
	}
}

필요한 헤더파일

profile
개인 기록공간

0개의 댓글