아날로그 비교기 추가

- 우측 아래에 가변 저항 2개가 AIN0, AIN1에 연결되어 있다.

 

아날로그 비교기 예제 1

- 풀링 방식으로 비교 후 LED shift

#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <util/delay.h>


/*
AIN1 핀 가변 저항과 AIN0 핀 가변저항 조절
AIN0 >= AIN1 -> LED 순차 점멸
아날로그 비교기 출력 ACO를 풀링으로 체크
*/
unsigned char led = 0xfe;

int main()
{
	DDRC = 0xff;
	DDRE = 0b00000010; //AIN(PE2), AIN1(PE3) 입력 설정
	ACSR = 0x0; // Analog Comparator Control and Status Registor
	SFIOR = 0x0; // Special Function IO Registor 
				 // 3번째 비트 ACME = 0 -> AIN1에 음 입력 전압
	
	PORTC = led;
	
	while(1){
		if(ACSR & 0x20){ // ACSR의 0x20 = ACO 아날로그 비교기 출력 비트가 1인지 확인
			led <<= 1;
			led |= 0x01;
			if(led == 0xff)
				led = 0xfe;
			PORTC = led;
			_delay_ms(1000);
		}
		
	}
}

 

풀링 방식은 잘 되는데,

인터럽트 방식에서는 토글이 잘 안되선지 인터럽트가 한번만 동작하고 만다. 그냥 pass

 

 

ADC도 fnd 쓰기도하고, 입력 받는데서 자꾸 워닝뜨길래 pass

 

 

 

USART

- atmega128에서는 USART 2개 내장, 클럭부, 송신부, 수신부로 구성

- 관련 레지스터로 UDR(IO 데이터 레지스터), UCSRA/B/C(제어 상태 레지스터) 3개, 보레이트 레지스터 UBRRH, UBRRL 2개로 총 6개

- UDR을 송신 데이터 버퍼 레지스터, 수신 데이터 버퍼 레지스터 두 용도로 사용, 같은 주소를 가지나 실제로는 분리되어 송신시 송신 데이터 버퍼 TXBn에 쓰고, 수신시 수신 데이터 버퍼 RXBn의 값을 읽는다.

 

USART 데이터 포맷과 통신 순서

1. 제어 레지스터로 통신 설정(동기/비동기, 데이터 비트 수, 정지 비트수 등)

2. 보레이트 레지스터로 전송속도 설정

 

 

 

USART를 추가한 KUT-128 회로

- 주의사항 : virtual terminal에서 rx/tx polarity를 inverted로 설정해야한다. normal로 했더니 보드레이트나 클럭을 잘 맞춰도 글자가 깨진다.

- 이걸 normal로 해놓고 rxd, txd를 거꾸로 연결해도 동작이 안된다.

 

USART 송신 하기

- 보레이트 9600bps, 정지비트 1비트, 패리티 x, 비동기 데이터 8비트

- 추가 : 아 그냥 문자열만 주면 줄바꿈이 안되서 뒤에 \r\n을 추가했다.

ref : https://www.avrfreaks.net/forum/uart-newline-n-issue

#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <util/delay.h>

void putch(char);

int main()
{
	char str[] = "This is USART0 control program\r\n";
	char *pstr;
	
	UCSR0A = 0x0;
	UCSR0B = 0b00001000;	//송신 인에이블 txen = 1 ->TxDn이 범용 IO포트가 아닌 송신 단자로 동작
	UCSR0C = 0b00000110;	// 비동기 데이터 8비트 모드	bit2/1 전송 데이터 비트 수 설정 11 -> 데이터 전송 8비트
	//UBRR 보 레이트 레지스터
	UBRR0H =0;				//Xtal = 16hz시 buad = 9600
	UBRR0L = 103;
	
	pstr = str;
	while(1){
		while(*pstr){
			putch(*pstr++);
			_delay_ms(1000);
		}
		pstr = str;
		_delay_ms(1000);
	}
}


void putch(char data){
	/*
	UDRE0 = 1?   UCRS0A의 5번째 비트 UDRE
	USART Data Register Emtry로 비어있으면 1 = 송신 준비 완료 인터럽트 발생
	*/
	while(!(UCSR0A & 0x20)){
		_delay_ms(1000);
	}
	// st -> 0 ~ 7(8개 데이터비트) -> (페리티 설정 x) -> stop bit(현재 1개)
	UDR0 = data;				// USART IO register에 데이터 전송
}

 

 

 

virtual terminal test 하기

 USART 송신 후 송수신 실험을 하려고 했는데, 입력을 해도 제대로 동작이 안됬다.

terminal에 입력한게 재대로 전송이 되고 있는지 확인하기 위해 잠깐 구글링 해봤더니

두 터미널을 연결해서 타이핑하면 반영이 되더라 아래 링크는 그 내용

ref: https://electronics.stackexchange.com/questions/420487/cant-type-on-virtual-terminal-proteus

추가 : 또 보다보니 실제 COM 포트를 프로테우스 시뮬레이션 상으로 연동해주는게 있었다.

기회되면 한번 만져봐도 좋을거같다.

ref : https://www.theengineeringprojects.com/2013/05/how-to-use-virtual-terminal-in-proteus.html

 

 

USART 송수신 테스트

- 지금 실제 kut-128 키트가 아닌 proteus 시뮬레이션 환경에서만 사용하다보니, 예제처럼 제대로 동작되지 않는다.

- 애초에 가상 터미널 1개에다가 송신 모드로 잡아놓고  쓰다보니 그 터미널을 echo type 설정을 해서 쓴다고 USART0로부터 값을 수신을 못하니 원하는데로 동작안하는게 당연했다.

- 그래서 atmega128에서는 USART 2개가 제공되므로 가상 터미널 2개를 놓고, 하나는 타이핑 입력 송신 터미널, 남은 하나는 결과 수신 터미널로 잡고 약간 회로와 코드를 변경해서 구현했더니 잘 동작하더라.

 

 

- 천천히 칠땐 괜찮지만 비동기 통신에다가 패리티 체크도 안하다보니, 타이핑을 빠르게 하면 수신 터미널에서 제대로 전달받지 못한다.

 

 

 

마지막으로 이걸 인터럽트로 바꿔보자

고치다가 찾은건데 USART 하나로 송수신 할수 있더라.

이게 전이중 방식이 가능한걸 잊었다.

----

인터럽트 처리가 잘 안되서 일단 여기까지 하고 해결하면 추가 예정

 

--------

220616-1821

아직 인터럽트 문제는 해결 못했고, 아래 표의 포멧처럼 USART 데이터가 날라가는지 보기위해 한번 실험해보았다.

전송 속도는 9600bps이니까

1bit 전송에 대강 0.1ms 정도 걸리겠다.

아래의 코드 대로 first, second, third 처럼 찍어서 보내게 했다.

 

#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <util/delay.h>


unsigned char first = 0b00110001;
unsigned char second = 0b00110010;
unsigned char third = 0b10000001;
unsigned char fourth = 0b10100101;

int main()
{
	DDRC = 0xff;
	PORTC = 0xff;
	// 송신 to ocsil
	UCSR0A = 0x0;
	//송신 완료 인터럽트 벡터 인에이블, 송신 인에이블 txen = 1 ->TxDn이 범용 IO포트가 아닌 송신 단자로 동작
	UCSR0B = 0b01001000;
	// 비동기 데이터 8비트 모드	bit2/1 전송 데이터 비트 수 설정 11 -> 데이터 전송 8비트
	UCSR0C = 0b00000110;
	//UBRR 보 레이트 레지스터
	UBRR0H = 0;	
	UBRR0L = 103;

	while(1){
		putch(first);
		_delay_ms(20);
		putch(second);
		_delay_ms(20);
		putch(third);
		_delay_ms(20);
		putch(fourth);
		_delay_ms(1000);
	}
}

void putch(char data){
	while(!(UCSR0A & 0x20));
	UDR0 = data;
}

 

프로테우스에서 제공하는 오실로스코프 크기 조절이 안되서

일단 전체 USART 데이터를 볼수 있도록 스케일을 낮춰놨다.

대강 1bit당 0.1ms 가까이 나온다.

 

 

unsigned char first = 0b00110001;
unsigned char second = 0b00110010;
unsigned char third = 0b10000001;
unsigned char fourth = 0b10100101;

 

first 변수에는 1을 2진화 한 값을 담아 보냈다.

이걸 USART 프레임으로 만들면 데이터는 8비트, 스탑 비트 스타트비트는 각각 1개이니 총 10비트로

9600bps이므로 1개는 0.1ms 이고, 10개이므로 1ms 정도 걸린다.

 

max232에서는 반전된 결과가 나오고 있어서 원래 뒤집히도록 나오는걸 알고 있었지만

왜 데이터 비트자리에 0b00110001를 반전해서 안나오나 싶었는데

위의 프레임 포멧을 자세히 보면 데이터 비트 LSB가 가장 앞에서 나오고 있으므로

00110001이 반대로 10001100으로 나오고 앞뒤로 스타트 스탑 비트가 붙는거였다.

  

 

 

 

나머지 값도 이런식으로  나올테니 넘어가고

원래는 왜 인터럽트 처리가 안되는지 보려고 했는데

지금 와서 보니까 이전에 저장한 프로젝트의 코드까지 현재 코드의 내용들로 덮어씌워져서 다날라갔다.

여기다가 중간 중간에 코드블록 해서 올렸는데, 폴링 방식으로 송수신한 코드도 사라졌다.

 

일단 USART는 여기까지 봤으니 통신은 넘어가고 나머지 하드웨어도 다뤄봐야겠다. 

+ Recent posts