Atmega8A 칩을 사용해 UART, SPI 통신을 구현할 것입니다.
Atmega를 Master칩으로 설정하고, GPIO 핀을 활용해 연결된 Slave칩들의 핀들까지 컨트롤 할 것입니다.
따라서 코드를 그대로 적용할 시 작동이 안 될수도 있습니다,,!
그리고 데이터 시트에서 기초 통신 코드를 어셈블리코드와 C코드로 간략하게 기술되어 있습니다. 저도 그 코드를 일부 참고해서 작성했으니, 웬만하면 데이터시트를 먼저 참고해주세요 :>
< 데이터시트 참고해 SPI통신과 UART통신 설정>
1. SPI 설정
최소한의 기능으로 동작하기 위해서 라이브러리를 사용하지 않고, GPIO핀을 조작해 직접 SPI 구현할 것입니다.
- SPI_MasterInit() : 핀 설정
SCK, MOSI, NSS를 Output으로설정하고 MISO핀만 Input으로 설정합니다.
(내장라이브러리를 사용해 SPI를 구현할 것이면, SPCR |= (1<<SPE)|(1<<MSTR); 처럼 SPI 활성화 및 마스터설정을 해줘야 합니다.)
void SPI_MasterInit(void) // GPIO
{
// InOut Pin set
DDRB |= (1<<SCK)|(1<<MOSI)|(1<<NSS);
DDRB &= ~(1<<MISO);
}
- SCK 핀을 1, 0으로 만들어주기 위한 매크로 구현
#define SCK_1 PORTB |= 1<<PORTB5;
#define SCK_0 PORTB &= ~(1<<PORTB5);
- SPI_Write() : addr 주소에 data 메모리 쓰기 구현
void SPI_WRITE(u8 addr, u8 data)
{
u8 tmp;
u8 mask = 0x80;
// MSB를 체크하며 1,0값을 핀에 실어서 보낸다
// 왼쪽으로 쉬프트하면서 데이터를 스캔
addr = (addr<<1)&0x7F;
NSS_0 // SPI 통신 시작 - SCK핀에 따라서 동작 진행
// SCK 핀을 올렸다 내렸다 8번 반복하며 MOSI 핀의 addr 데이터가 전송된다
for (u8 i=0;i<8;i++)
{
if (addr & mask) {
MOSI_1
}
else MOSI_0
addr = addr<<1;
SCK_1
SCK_0
}
for (u8 i=0;i<8;i++)
// SCK 핀을 올렸다 내렸다 8번 반복하며 MOSI 핀의 data 데이터가 전송된다
{
if (data & mask) {
MOSI_1
}
else MOSI_0
data = data<<1;
SCK_1
SCK_0
}
NSS_1
}
- SPI_READ()
u8 TRH_READ(u8 addr)
{
u8 tmp;
// MSB를 체크하며 1, 0값을 핀에 실어서 보낸다
// 왼쪽으로 쉬프트하면서 데이터를 스캔
u8 mask = 0x80;
unsigned char result = 0;
addr = (addr<<1)|0x80;
NSS_0 // SPI 통신 시작 - SCK핀에 따라서 동작 진행
for (u8 i=0;i<8;i++)
{
if (addr & mask) {
MOSI_1
}
else {
MOSI_0
}
addr = addr<<1;
SCK_1
SCK_0
}
for (u8 i=0;i<8;i++)
{
// 핀에 입력될때, result LSB += 1
if(PINB & (0x10)) { // INPUT = PIN!
result += 0x01;
}
SCK_1
SCK_0
if (i != 7) result <<= 1;;
}
NSS_1
return result;
}
2. UART 설정
UART는 데이터시트를 살펴보면 관련 레지스터가 있습니다.
- UBRRH (0x20) : Baud Rate 설정 레지스터
아래와 같이 설정하고자 하는 속도를 매크로로 정의했습니다.
#define BAUD 9600
#define MYUBRR FOSC/16/BAUD-1
- USART_Init() : 통신 속도 설정
초기화할때 설정한 MYUBRR을 매개로 실행합니다. -> USART_Init(MYUBRR);
void USART_Init(unsigned long baud)
{
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);
}
- USART_Transmit() :
UCSRA라는 Status 레지스터를 통해 UDR 버퍼가 제대로 비워지고 채워졌는지 확인할 수 있습니다.
void USART_Transmit( unsigned char data )
{
/* Wait for empty transmit buffer */
while ( !( UCSRA & (1<<UDRE)) )
/* Put data into buffer, sends the data */
UDR = data;
}
'F💻W > Coding' 카테고리의 다른 글
c언어 uint8_t 16진수 변수 10진수 시리얼 출력 방법 (0) | 2024.01.12 |
---|---|
STM32 개발 시, delay 함수 직접 구현해서 사용해보자 ! (0) | 2023.12.06 |
ATMEGA UART 출력 (0) | 2023.11.21 |
gpio mode 참고 (0) | 2023.07.10 |
Silicon Lab EFR32 코드 분석 (0) | 2023.06.26 |
[STM32F030C6T6] Bootloader 구현 (3) | 2023.03.30 |