atmega128하고 DTM-M300이라는 온도측정하는 센서를 이용하여 온도를 측정하려고 하는데요.
이 온도센서가 SPI MASTER 방식으로 MCU랑 통신한다고 하더군요.
온도값은 LED로 나타나게 하려고 하는데요.
그런데 자꾸 안되네요 어디서 문제인지 잘 모르겠어요...
데이터시트 주소를 올려두겠습니다. 데이터시트 맨 마지막 부분에 예제 소스가 있습니다. 그대로 한것 같긴 한데...
일단 연결은
INT-> PB0
SCK->PB1
SI->PB3
SO->PB3
이렇게 했고요.
Vcc랑 SI에는 레귤레이터 3.3V짜리 연결 했습니다.
이거는 소스입니다. 이거는 AVR STUDIO4로 짰습니다.
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
ISR(SPI_STC_vect);
void Initialization();
signed char Read_SPI_Receive();
signed char rx_data;
int transfer_start_flag = 0;
int datum = 0;
int store_enable_flag = 0;
signed char temp_data[4] = {0};
signed char Target_temp_H = 0;
signed char Target_temp_L = 0;
signed char Ambient_temp_H = 0;
signed char Ambient_temp_L = 0;
signed char Target_temperature = 0;
signed char Ambient_temperature = 0;
int i = 0;
void Initialization()
{
DDRA = 0xff;
DDRB = 0x08;
PORTB = 0x01;
SPCR = 0xaa;//SPIE enable, SPI disable, LSB 전송, Slave Select, Leading Edge 하강에지 Trailing Edge 상승에지, 64khz
SPSR = 0x00;
}
ISR(SPI_STC_vect)//외부 인터럽트 루틴
{
if((PINB & 0x01) == 0) //DTM-M300 의 INT 포트에 연결된 사용자 포트 상태가 low 일때
{
SPCR |= 0x40;
transfer_start_flag =1; //전송 시작 FLAG set
}
else //DTM-M300의 INT 포트가 High 로 level 변화 시 SPI disable
{
SPCR &= 0xaa;
}
}
signed char Read_SPI_Receive()
{
signed char data = 0;
while((SPSR & 0x80) == 0);
data = SPDR;
return data;
}
void main()
{
Initialization();
sei();
while(1)
{
if(transfer_start_flag == 1) //외부 인터럽트에 의해 전송시작 Flag 가 Set 되면
{
rx_data = Read_SPI_Receive();//Read_SPI_Receive();//Read_SPI_Receive(); //SPI 데이터 수신/ 저장
// 데이터가 0xA1 일 경우 나머지 4Byte data 를 temp_data[datum] array 에 저장
if(rx_data == 0xA1) //※Figure 6.1: Timing of SPI 참고
{
transfer_start_flag =0;
datum=0;
store_enable_flag =1;
}
else
store_enable_flag=0;
}
if((store_enable_flag == 1) && (datum < 4))
{
for(i=0; i<4; i++)
{
rx_data = Read_SPI_Receive();//Read_SPI_Receive();//Read_SPI_Receive();
temp_data[datum]=rx_data;
datum++;
}
}
if(datum == 4) // 0xA1(1Byte),target 온도(2Byte),주변 온도(2Byte) 수신 완료 시
{
Target_temp_H = temp_data[0]; //Target 온도 상위 1 Byte
Target_temp_L = temp_data[1]; //Target 온도 하위 1 Byte
Ambient_temp_H = temp_data[2]; //주변 온도 상위 1 Byte
Ambient_temp_L = temp_data[3]; //주변 온도 하위 1 Byte
Target_temperature = ((Target_temp_L) | (Target_temp_H <<8)); //Target 온도 2 Byte
Ambient_temperature = ((Ambient_temp_L) | (Ambient_temp_H <<8)); //주변 온도 2 Byte
}
PORTA = Target_temperature;
_delay_ms(500);
PORTA = 0x00;
}
}
SI와 SO를 둘 다 PB3 에 연결했다고요?
일단 핀배치는 (센서 -> MCU) SO -> MOSI [PB2], SI -> MISO[PB3] 로 하셔야 합니다.
또한, 센서는 SPI Mode 3으로 동작하고 있으므로 SPCR 레지스터 설정을 CPOL=1, CPHA=1로 하셔야 합니다
참고로 INT -> /SS [PB0] 신호 처리는 MCU 가 스스로 할 수 있습니다. MCU는 /SS 가 0일 때에만 SPI로부터 입력을 받습니다.
따라서 처음 Initialization 과정에서부터 SPCR 레지스터의 SPE 값을 1로 설정해도 괜찮습니다
인터럽트 설정이 잘못되었습니다. 센서 메뉴얼 8~10쪽에서 언급한 \'Ext interrupt routine\' 는 MCU의 INT0~INT7 [PD0-PD3, PE4-PE7] 을 의미합니다.
프로그램에서 사용하고 있는 SPI_SPC_vec 인터럽트는 SPI를 통해 1byte 가 수신 (또는 송신)되었을 때 걸리는 인터럽트입니다.
답변 감사합니다~ 그렇다면 INT-> /ss 로 연결한다면, 외부 인터럽트(PD0~3, PE4~7)로는 어떤 것을 연결해야 하나요? 아애 연결할 필요 없다면, 데이터 시트에서 나온 Ext interrupt routine부분의 소스는 어디에 집어넣어야 하는건가요...ㅠㅠ 휴 어렵네요 ㅠㅠ
헐.. 온도센서가 마스터로 동작하다니... 그럼 계속 온도센서 스스로 온도를 보내주는 방식인가요?
만약 그렇다면 mcu에 /ss로 연결해야 하고요, mcu가 마스터 온도센서가 슬레이브라면, /ss나 인터럽트 핀에 연결할 필요 없이 그냥 gpio로 로우신호 인가해서 선택해도 됩니다.
mcu가 슬레이브가 되고 센서가 마스터에요 ^^ㅋ spi통신에 대해 처음 해보는거라...휴 ㅠㅠ