BASIC4MCU | 질문게시판 | Ws2812를 이용한 시계 ( Ws2812코드와 시리얼 코드 질문)
페이지 정보
작성자 ParkKH 작성일2021-06-05 21:53 조회5,919회 댓글4건첨부파일
본문
안녕하세요!
Ws2812를 이용해서 시계를 만들었는데
지금은 Ds1302 RTC를 이용해서 시계를 작동중입니다.
근데 저는 여기서 esp8266이라는 와이파이 모듈을 이용하여
앱에서 색상제어와 함께 LED 모드 등을 설정하고 싶어
앱 ----웹---- esp8266 ----시리얼---- Atmega328P 이런식으로 구성하여 제어하려고 합니다.그러나 값을 받아오려고 수신 인터럽터를켜면 메인문에 있는 LED 제어문들이 정상작동을 안하고
수신 인터럽터 없이는 어떻게 32비트의 값을 받아오는지를 잘 몰라서 선생님께 도움을 요청해봅니다.
Ws2812 구동 부분은 헤더와 라이브러리 파일 내에 있습니다. 혹시 몰라 제가 연습했던 시리얼쪽 코드도 보내드리겠습니다.
헤더와 라이브러리는 제가 코드비전의 기본 헤더와 라이브러리를 참고하면서 만든거라 난잡할수도 있습니다^^;
댓글 4
조회수 5,919master님의 댓글
master 작성일
여러바이트(2바이트 이상)의 전송은 포멧을 만들어서 전송해야 합니다.
32바이트의 구성내용이 무엇인지 모르겠군요
test.c에서는 LCD에 32바이트를 출력하는 것으로 전송시험 하고 있나요?
그렇다면 연산을 하지말고 버퍼 내용을 그대로 출력하면 되는 것 아닌가요?
우선 LCD에 출력만 한다고 하면
'@' + 32바이트'0'~'9'범위의 데이터 + '#' 이런식으로 문장의 시작과 끝을 포함해서 34바이트를 전송하면 쉽습니다.
LCD의 lcd_gotoxy()함수는 lcd_putchar() 함수보다 시간이 더 걸립니다.
32번의 함수 실행은 시간이 많이 소요될 수 있습니다.
master님의 댓글
master 작성일
#include <io.h>
#include <i2clcd.h>
#include <delay.h>
#include <string.h>
//
const unsigned char font[10]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39};
//
bit rx_flag=0;
char r,rx_cnt=0,rx_buf[50],lcd_buf[4][9],str[50];
//
interrupt [USART_RXC] void usart_rx_isr(void){
char i;
r=UDR;
if(r=='@'){ rx_cnt=0; } // STX
else if(r=='#'){ // ETX
if(rx_cnt==32){ // data 길이가 32바이트가 맞으면
for(c=0;c<8;c++)lcd_buf[0][c]=rx_buf[c]; // lcd1 buf에 복사
for(c=0;c<8;c++)lcd_buf[1][c]=rx_buf[c+ 8]; // lcd2 buf에 복사
for(c=0;c<8;c++)lcd_buf[2][c]=rx_buf[c+16]; // lcd3 buf에 복사
for(c=0;c<8;c++)lcd_buf[3][c]=rx_buf[c+24]; // lcd4 buf에 복사
lcd_buf[0][8]=lcd_buf[1][8]=lcd_buf[2][8]=lcd_buf[3][8]=0; // null
rx_flag=1;
}
rx_cnt=0;
}
else{ // data
if(rx_cnt<40)rx_buf[rx_cnt++]=r; // rx_buf에 저장
}
}
interrupt [TIM0_OVF] void timer0_ovf_isr(void){
//void TX_CH(char ch){while(!(UCSRA==0x20))UDR=ch;}
void main(void){
char i;
TCCR0=(0<<CS02) | (1<<CS01) | (1<<CS00); TCNT0=0x06;
TIMSK=(0<<OCIE2) | (0<<TOIE2) | (0<<TICIE1) | (0<<OCIE1A) | (0<<OCIE1B) | (0<<TOIE1) | (1<<TOIE0);
UCSRB=(1<<RXCIE) | (1<<TXCIE) | (0<<UDRIE) | (1<<RXEN) | (1<<TXEN) | (0<<UCSZ2) | (0<<RXB8) | (0<<TXB8);
UCSRC=(1<<URSEL) | (0<<UMSEL) | (0<<UPM1) | (0<<UPM0) | (0<<USBS) | (1<<UCSZ1) | (1<<UCSZ0) | (0<<UCPOL);
UBRRL=103;
DDRC=1;
lcd_init(); lcd_clear(); lcd_backlighton();
#asm("sei");
while(1){
if(rx_flag==1){
lcd_gotoxy(0,1); lcd_putstring(lcd_buf[0]);
lcd_gotoxy(0,2); lcd_putstring(lcd_buf[1]);
lcd_gotoxy(0,3); lcd_putstring(lcd_buf[2]);
lcd_gotoxy(0,4); lcd_putstring(lcd_buf[3]);
rx_flag=0;
}
}
}
lcd_putstring() 함수명은 임의로 작성했으니 라이브러리에서 제공하는 함수명으로 수정하세요
ParkKH님의 댓글
ParkKH 작성일
우선 답변 정말 감사드립니다!
test.c는 ESP-01칩에서 아스키코드로 되어있는 4바이트의 값을 atmega328로 받아 정수로 변환하여 data값에 4바이트를 밀어넣는것을 테스트하는 코드였습니다.
선생님의 코드를 적용시켜 LCD에 적용시키는것까지는 성공을 하였습니다.
하지만 ws2812 코드에 인터럽터를 활성화 하니 ws2812에서 잔상과 이상동작이 발생하고 있습니다.
이 방법을 해결하고자 인터럽터를 비활성화 하고 값을 받아보려니 순차적으로 4바이트의 값을 어떻게 받아와야할지가 난관입니다.
선생님께서 해결방향을 제시해주시면 정말 감사드리겠습니다.
바이트별 담겨있는 값 정보입니다.
1바이트: red색상코드
2바이트: green색상코드
3바이트: blue색상코드
4바이트: (0~2)비트 LED 모드 8가지, (3~7) 여유분 비트
master님의 댓글
master
ws2812 코드에 인터럽터를 활성화 하니 ws2812에서 잔상과 이상동작이 발생하고 있습니다. <-- 여기에서 테스트한 코드를 첨부하세요