/*....................................*/
void spi_init(void)
{
SPI_DDR |= (1 << MCP_CS)|(1 << MCP_SDI)|(1 << MCP_SCK);
SPI_DDR |= (1 << MCP_LDAC)|(1 << MCP_SHDN);/// LDAC 입력이 Low 가 되도록 PB4 가 Low 가 출력되게 설정됨
SPI_PORT |= (1<<MCP_SHDN)|(1 << MCP_CS);
SPCR = (1 << SPE)|(1 << MSTR);
SPSR = (1 << SPI2X);
}
/*....................................*/
void port_init(void)
{
PORTB = 0x00;
DDRB = 0xff; //LDAC 입력이 Low 가 되도록 PB4 가 Low 가 출력되게 설정됨
ATmega8 데이터시트에 보면 SPI 설명 항목에서 위의 표가 있습니다.
이 표에 의하면 SPI 기능이 선정되면 MISO 단자는 입력이 된다고 되어 있습니다.
즉 PB4(MISO) 는
SPCR = (1 << SPE)|(1 << MSTR);
명령을 수행한 결과 Master 가 되면서 MISO 는 기존에 DDR 설정을 무시(Override) 하고 입력단자로 탈바꿈한다는 겁니다.
여기서 PORT 레지스터 설정 값은 어떻게 된다는 건 안 보이네요.
즉 PORTB 레지스터는 앞에
void port_init(void) 함수에서 PORTB = 0x00;
로 선언되어 있고
void spi_init(void) 함수에서
SPI_PORT |= (1<<MCP_SHDN)|(1 << MCP_CS);
로 선언되어 있어서
PORTB4(MISO) 레지스터 값은 따로 또 1 로 만들지 않음으로써
PORTB4(MISO) 레지스터 값은 0 이 되어 보입니다.
이 말은 PB4(MISO) 단자가 입력모드인데 내장된 PULL-UP 저항이
사용되지 않는 다는 것으로 Tri-state (Hi-Z) 상태가 된다는 것입니다.
말을 바꾸면 PB4(MISO) 단자가 전기적으로 끊어진 상태와 비슷해 집니다.
결국은 DAC 의 LDAC 입력이 아무것도 연결되지 않은 상태와 비슷하고 그래서 주변의 노이즈에 따라 되다 안되다 했나 봅니다.
이 말은 바벨2세 님이 지적하신 대로 LDAC 입력이 확실한 High 도 아니고 Low 도 아닌 상태로 붕붕 떠 있는 상태가 됩니다.
나름대로 해결책을 고민해 보았는데요.
SPI 통신이 끝나면
SPI 기능을 없애서 PB4(MISO) 가 PORTB 레지스터와 DDRB 레지스터의 영향만을 받아서 출력으로 동작하고
다시 SPI 통신이 필요하면 SPI 기능을 살리는 것으로 하면 될 것 같습니다.
/*....................................*/
void write_mcp4801(unsigned int val )
{
SPCR = (1 << SPE)|(1 << MSTR);
SPI_PORT &= ~(1 << MCP_CS); // select
spi_xmit((unsigned char)(val >> 8));
spi_xmit((unsigned char)val);
SPI_PORT |= (1 << MCP_CS); // deselect
SPCR &=~(1 << SPE); // SPI 기능을 정지시킴.
SPI_DDR |= (1 << MCP_LDAC)|(1 << MCP_SHDN); // 이건 없어도. 될 듯..??
}
실제 시험은 안 해 보았습니다.
아직 AVR-GCC를 사용해 본 적이 없어서
test 는 다른 분에게 부탁드립니다.
첫댓글 그냥은 되다 안되다 하고 pull-down 저항을 연결하면 잘된다면 반대로 pull-up 저항을 달면 전혀 안 될 것입니다.
그래서 기존의 프로그램을 pull-up 저항을 달고 프로그램 test 하고 제 아이디어로 수정한 프로그램을 test 해 본다면
결과가 금방 나타날 것으로 생각합니다.
SPI 기능이 Shift Register 기능을 사용하는 것이기에
Hardware 기능 대신에 Software 로 Shift Register 기능을 만들어도 될 것입니다.
SPI 통신이 필요하면 SPI를 OPEN하고 사용이 끝나면 Close시키고 Port를 0 출력으로 만들면 될 것 같습니다. 프로그램을 보내 주실수 있나요? 제가 AVR관련 장비와 AVR-GCC로 개발 환경을 가지고 있습니다.
저항 연결해서 잘 되니까(사실은 저항없이도 그동안 잘 되었기에 무심했었죠. 그러나 100개를 만들어도 같은 결과가 나와야겠지요) 저는 저항 연결로 만족하고 프로그램은 손 대지 않으려 합니다.
이메일 주소를 알려 주세요. 소스코드를 보내 드리지요. (소스코드는 프로젝트자료실에 올려져 있어서 병장이면 볼 수 있습니다. 얼른 진급하세요.ㅋㅋ)
PORTB = 0x00; DDRB = 0xff; 에서 이미 필요한 조치(??) 를 취했기에
마지막 함수 void write_mcp4801(unsigned int val )에서의 빨간색 루틴 즉 spi 기능을 동작/ 정지 시키는 것만 추가하면 될 것입니다.
LCD 조명을 끄려면 케이블의 1~14번 중 11, 12번(같이 연결되어 있음) 선을 끊으면 되는데요,
좀 더 쉽게 하려면 수직으로 세워져 있는 R14 윗 부분을 끊고 거기에 스위치를 연결하시면 됩니다.
조명 끄면 글자가 희미하게 보이는데요.