Electoday 4.0

ไมโครคอนโทรลเลอร์ => AVR and Arduino => Topic started by: manaw on February 11, 2013, 07:41:11 pm

Title: ช่วยหนูแก้ code หน่อยคะในการใช้ PORT ร่วมกัน
Post by: manaw on February 11, 2013, 07:41:11 pm
ตอนนี้ต้องการใช้ POTRD 4 บิท เป็น Output ให้กับ 7 segment [ออกเป็น BCD ให้กับ CD4543] 
และที่เหลืออีก 4 บิท เป็นขาควบคุม digit 7 segment คะนั่งงมมา 4 ชม.และงงมั๊กมาก

Code: [Select]
Project: Alarm Clock
 By : มะนาว
 MCU : ATMEGA16A-PU
 Date : 10/02/2013
*********************************************************************/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <compat/deprecated.h>

#define     F_CPU 8000000UL
#include    <util/delay.h>

#define segment_PORTD PORTD
#define segment_DDRD DDRD

#define digit_PORTD PORTD
#define digit_DDRD DDRD

/*********************************************************************/
const unsigned int segment[10] ={ 0x00,0x10,0x20,0x30,0x40, //0,1,2,3,4
                                     0x50,0x60,0x70,0x80,0x90, //5,6,7,8,9
};
/*********************************************************************/
unsigned int msec=1000;

unsigned int count[3]={7,1,0};

/*********************************************************************/
void display(void) // Function Display
{
segment_PORTD = segment[2]; //  [88:88:8x]
digit_PORTD = 0x0E;                //  ON  = [88:88:8x]
_delay_ms(1); //   [delay ON/OFF]
digit_PORTD = 0x0F;               //   OFF = [88:88:8x]

segment_PORTD = segment[0]; // [88:88:x8]
digit_PORTD = 0x0D; // ON  = [88:88:x8]
_delay_ms(100); // [delay ON/OFF]
digit_PORTD = 0x0F; // OFF = [88:88:x8]

}
/*********************************************************************/

int main(void)
{
segment_DDRD = 0xF0; // Set Out_put----->7segment
digit_DDRD = 0x0F; // Set Digit_Port-->7segment

while(1) // Loop
{
display();
}
return 0;
}
Title: Re: ช่วยหนูแก้ code หน่อยคะในการใช้ PORT ร่วมกัน
Post by: AnutSangka on February 11, 2013, 07:56:14 pm
ตรงกำหนด Direction port
ถ้าผมเข้าใจไม่ผิดคือ Port D ทั้ง 8 Bit นำไปควบคุม 7 segment Driver ทั้งสองตัวใช่มั้ย

ถ้าเป็นอย่างให้แก้เป็น

DDRD = 0xff;

บรรทัดเดียวเลยครับ
เพราะจาก โค้ดของ คุณ
               segment_DDRD   = 0xF0;         // Set Out_put----->7segment                                                      
   digit_DDRD   = 0x0F;         // Set Digit_Port-->7segment


บรรทัดแระจะทำให้บิทที่ 0-3 เป็น input
บิทที่ 4-7 เป็น Output
แต่ถอมาบรรทัดที่สอง (0-3 output 4-7 input)


ดังนั้นให้แก้เป็น 0xff ครับ คือทั้ง 8 บิทเป็น Output ครับ  :) :)

อ่อเพิ่มเติม ตรง Function display(void)

เช็คด้วยนะครับ

บรรทัดแรกของคุณ

segment_PORTD = segment[2];
ต่อมาก็สั่งมาที่
digit_PORTD = 0x0E;

แบบนี้คำสั่งที่ออกมาได้จะมีแค่ digit_PORTD = 0x0E; ครับ

แต่ถ้าต้องการให้ สถานะบิทในคำสั่งแรกคงสถานะไว้แนะนำให้ใช้ Operator    |= ครับ เช่น

segment_PORTD = segment[2];
digit_PORTD |= 0x0E;

แบบนี้ครับ
Title: Re: ช่วยหนูแก้ code หน่อยคะในการใช้ PORT ร่วมกัน
Post by: manaw on February 11, 2013, 08:12:03 pm
แก้ตามที่บอกแล้วคะ ยังไม่ดีเลยคะ
Title: Re: ช่วยหนูแก้ code หน่อยคะในการใช้ PORT ร่วมกัน
Post by: AnutSangka on February 11, 2013, 08:13:49 pm
แก้ตามที่บอกแล้วคะ ยังไม่ดีเลยคะ

ลองใหม่ดูครับ ผม Modify ข้อความข้างบนเมื่อกี้นี้

อ่าน การใช้งาน 7 Segment Driver ให้ดีครับ 

ผมไม่เคยลองใช้ Driver ซะด้วย เคยแต่ต่อตรงเลย  ;D ;D

อีกอย่างคือปรับเรื่องการ Delay ด้วยครับ delay_ms(1) นี่มันไวเกินครับตามนุษย์สังเกตไม่ทันหรอกครับ
Title: Re: ช่วยหนูแก้ code หน่อยคะในการใช้ PORT ร่วมกัน
Post by: manaw on February 11, 2013, 08:22:46 pm
คือเดิมทีใช้ทั้ง PORTD ไดร 7 segment อย่างเดี่ยวคะ ถ้าทำตามที่แนะนำก็ออกคะใช้การได้
แต่ตอนนี้ต้องการลดการใช้งาน PORT ลงโดยการใช้ทั้ง PORT ให้เป็นทั้ง Output แบบนี้คะ
       บิทที่ 0-3 เป็นการควบคุม digit ของ 7 segment
       บิทที่ 4-7 เป็น output ออกเป็น BCD เพื่อใช้กับ IC CD4543 คะขับ 7 segment คะ
Title: Re: ช่วยหนูแก้ code หน่อยคะในการใช้ PORT ร่วมกัน
Post by: JENG on February 11, 2013, 09:20:54 pm
Code: [Select]
//Project: Alarm Clock
//// By : ÁйÒÇ
// MCU : ATMEGA16A-PU
/// Date : 10/02/2013
//*********************************************************************/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <compat/deprecated.h>

#define     F_CPU 8000000UL
#include    <util/delay.h>

#define     COMMON1_ON()        PORTD |= 0x01
#define     COMMON2_ON()        PORTD |= 0x02
#define     COMMON3_ON()        PORTD |= 0x04
#define     COMMON4_ON()        PORTD |= 0x08
#define     COMMON_ALL_OFF()    PORTD &= ~0x0f

#define     PASTE_SEGMENT(x)    PORTD &= ~0xf0; PORTD |= x<<4

unsigned char digit_cnt;

void scan_display(void) // Function Display
{
digit_cnt++;
COMMON_ALL_OFF();
    switch(digit_cnt)
    {

        case 1:
        PASTE_SEGMENT(1);
        COMMON1_ON();
        break;

        case 2:
        PASTE_SEGMENT(2);
        COMMON2_ON();
        break;

        case 3:
        PASTE_SEGMENT(3);
        COMMON3_ON();
        break;

        case 4:
        PASTE_SEGMENT(4);
        COMMON4_ON();
        digit_cnt=0;

    }

}
/*********************************************************************/

int main(void)
{

//segment_DDRD = 0xF0; // Set Out_put----->7segment
//digit_DDRD = 0x0F; // Set Digit_Port-->7segment

    DDRD = 0xff;

for(;;) // Loop
{
        _delay_ms(5);
scan_display();
}
return 0;
}
Title: Re: ช่วยหนูแก้ code หน่อยคะในการใช้ PORT ร่วมกัน
Post by: manaw on February 11, 2013, 10:50:41 pm
อ่านดูแล้วไม่ค่อยเข้าใจเลยคะ งงมากเลย เพิ่งหักเล่นด้วย ลองเบิร์นดูแล้วเหมือนเดิม
Title: Re: ช่วยหนูแก้ code หน่อยคะในการใช้ PORT ร่วมกัน
Post by: samira on February 11, 2013, 11:03:15 pm
อีกอย่างคือปรับเรื่องการ Delay ด้วยครับ delay_ms(1) นี่มันไวเกินครับตามนุษย์สังเกตไม่ทันหรอกครับ

สมมุติว่า ทำอย่างที่ จขกท ว่ามา คือ
ยิงภาพออก 7 segment หลักหน่วย แค่ 1 msec
จากนั้น ยิ่ง ออกหลักสิบ 1 msec เช่นกัน ......
เรียงไปเรื่อยๆ จนถึง digit ที่ 4 คือ หลักพัน จนครับ

จากข้อความข้างบน บอกว่า มันไวจนเกินตา มนุษย์สังเกตไม่ทันหรอก

ลองมาดูว่า มันจะเกิดอะไร

เมื่อหลักหน่วย แสดงภาพ แปลว่า 7 segment มันแสดงค่าออกมา แค่ เวลาสั้นๆ แต่..........
จากหลักของ Persistent of Vision ( POV) นั้น ภาพมันยังบันทึกอยู่ในตา(ในสมอง) ของเราในส่วนที่เรียกว่า Visual cortex
กล่าวคือ สมองเรายังบันทึกภาพอันนั้นอยู่และจะคาให้เราเห็นภาพนั้นอยู่ อย่างน้อย ~ 30 msec

ต่อจากนั้น ภาพของหลักสิบ ก็จะเกิดขึ้นเป็นเวลา 1 msec และจะคาในตาของเราอยู่อีก แปลว่า.......
ตาของเราตอนนี้ จะเห็นหลัก หน่วยและหลักสิบ
ขบวนการนี้ จะเกิดขึ้นอีกในหลักร้อย และ หลักพัน

เมื่อครบแล้ว เนื่องจากมันเกิดขึ้นภายในเวลาทั้งหมด 4 หลัก ภายใน 4 msec เราก็จะเห็นคาติดในตาของเราอยู่อย่างนั้น
และก็จะวนไปอีกจากหลักหน่วย ถึง หลัก พัน ทำให้เราเห็นภาพติดตา นั่นคือ POV
 
ที่ว่ามานี้ หาก ค่าที่อ่าน ไม่เปลียนเร็วมากนัก เช่น เรา update อุณหภูมิ ทุกๆ 1 วิ เป็นต้น

ดังนั้น คิดว่า การใช้ delay  1 msec นั้น ตาของเราจะเห็นเป็นภาพครบทั้ง 4 หลักครับ แต่...................

หากค่าของแต่ละหลักนั้นเปลียนอย่างรวดเร็ว เช่น counter ที่เขาใช้กันในทางวิทยาศาสตร์ เช่น Geiger Counter
ที่นับจำนวนสารกำมันตะภาพรังสี ที่มันแตกออกมาอย่างรวดเร็ว เราก็จะแทบอ่านไม่ทัน กล่าวคือ 7 segment มัน update ค่าใหม่ เร็วมาก

ดังนั้น การ delay จะทำให้อ่านข้อมูลที่แสดงใน 7 segment ทันหรือไม่นั้น ไม่ได้ขึ้นกับ delay นี้ แต่ มันขึ้นกับว่า ข้อมูลที่เอามาแสดง มันเปลียนเร็วหรือเปล่ามากกว่า

หวังว่า คงมีประโยชน์บ้าง
Title: Re: ช่วยหนูแก้ code หน่อยคะในการใช้ PORT ร่วมกัน
Post by: samira on February 11, 2013, 11:13:46 pm
Quote
/*********************************************************************/
const unsigned int segment[10] ={ 0x00,0x10,0x20,0x30,0x40, //0,1,2,3,4
                                        0x50,0x60,0x70,0x80,0x90, //5,6,7,8,9
                        };                        
/*********************************************************************/


ขอถาม จขกท หน่อยเถอะว่า segment[10] นี้ เอาใว้ทำอะไร ?
Title: Re: ช่วยหนูแก้ code หน่อยคะในการใช้ PORT ร่วมกัน
Post by: crywolf on February 11, 2013, 11:25:19 pm
โค๊ดแบบมั่วๆ แต่คิดว่าน่าจะใช้ได้ ลองดูเป็นแนวทางได้

Code: [Select]
unsigned int msec=1000;
volatile unsigned char second=0, minute=0, hour=0;

static inline void InitTimers(void)
{
// Clear Timer on Compare or CTC mode and Prescaler of 64
TCCR0 |= 1<<WGM01|3<<CS00;
//Enable compare match interrupt
TIMSK |= 1<<OCIE0;
//Set compare value for 1 mSec
OCR0 = (F_CPU / 64 / 1000)-1;
//Enable global interrupts
sei();                 
}

int main(void)
{
DDRD = 0xff;

InitTimers();

while(1)
{
// PORTD |= 0x0F;
PORTD = ((second % 10)<<4)|0x0E;
_delay_ms(1);

// PORTD |= 0x0F;
PORTD = ((second / 10)<<4)|0x0D;
_delay_ms(1);

// PORTD |= 0x0F;
PORTD = ((minute % 10)<<4)|0x0B;
_delay_ms(1);

// PORTD |= 0x0F;
PORTD = ((minute / 10)<<4)|0x07;
_delay_ms(1);
}

return 0;
}

ISR(TIMER0_COMP_vect)
{
if(--msec == 0)
{
msec = 1000;

if(++second > 59)
{
second = 0;
if(++minute > 59)
{
minute = 0;
if(++hour > 23)
{
hour = 0;
}
}
}
}
}
Title: Re: ช่วยหนูแก้ code หน่อยคะในการใช้ PORT ร่วมกัน
Post by: manaw on February 11, 2013, 11:39:43 pm


ขอถาม จขกท หน่อยเถอะว่า segment[10] นี้ เอาใว้ทำอะไร ?
[/quote]

สำหรับนำค่าในอาเรย์ขับออก 7 segment คะ เนื่องจากต้องการให้เอาท์พุตออกเป็น BCD
Title: Re: ช่วยหนูแก้ code หน่อยคะในการใช้ PORT ร่วมกัน
Post by: JENG on February 12, 2013, 12:26:18 am
ขอดูวงจรหน่อยซิ  :)
Title: Re: ช่วยหนูแก้ code หน่อยคะในการใช้ PORT ร่วมกัน
Post by: manaw on February 12, 2013, 12:45:15 am
ตามนี้คะ จริงๆตั้งใจจะทำ 4 digitคะแต่เกิดปัญหาเลยลดลงมาเป็น 2 digit
Title: Re: ช่วยหนูแก้ code หน่อยคะในการใช้ PORT ร่วมกัน
Post by: crywolf on February 12, 2013, 06:57:26 am
จากวงจรในรูป Code ที่ผมให้ไป น่าจะใช้ได้เลย และใช้ได้ถึง 4 หลัก ถ้าจะเอา 6 หลักก็เพิ่มได้ไม่ยาก

แต่แนะนำนิดนึงว่า ไม่ควรต่อ Common ของ 7-Segment เข้ากับขา Micro ตรงๆ
เพราะ ขาๆนึงของ Micro รับหรือจ่ายกระแสได้ไม่มาก การต่อตรงๆแบบนี้ ทำให้ ขา 1 ขา
ต้องขับ LED มากสุดถึง 7 ดวง (Segment) ควรใช้ Transistor หรือ Mosfet มาช่วย
Title: Re: ช่วยหนูแก้ code หน่อยคะในการใช้ PORT ร่วมกัน
Post by: firmware.c on February 12, 2013, 07:54:29 am
code ของท่าน JENG น่าจะใช้ได้แล้วนะครับ
Title: Re: ช่วยหนูแก้ code หน่อยคะในการใช้ PORT ร่วมกัน
Post by: JENG on February 12, 2013, 09:56:25 am
ถ้าน้องจะต่อ common กับ mcu ตรงๆให้แก้ code ตามนี้ (นึกว่าจะต่อผ่าน TR แบบ NPN)

#define     COMMON1_ON()        PORTD &= ~0x01
#define     COMMON2_ON()        PORTD &= ~0x02
#define     COMMON3_ON()        PORTD &= ~0x04
#define     COMMON4_ON()        PORTD &= ~0x08
#define     COMMON_ALL_OFF()    PORTD |= 0x0f

(http://image.free.in.th/z/iu/ademo.jpg) (http://pic.free.in.th/id/12f76394c2fd0a426c234712d3cdf501)
Title: Re: ช่วยหนูแก้ code หน่อยคะในการใช้ PORT ร่วมกัน
Post by: manaw on February 12, 2013, 05:31:56 pm
ทำได้แล้วคะพี่ๆทุกคน แก้ไขโดยจากการ set 7 segment ในบิทที่ 0-3 เป็น higt ทุกตัวก็ได้แล้วคะ

ขอบคุณพี่ๆทุกคนที่ให้ความช่วยเหลือนะคะ