ช่วยหนูแก้ code หน่อยคะในการใช้ PORT ร่วมกัน

Started by manaw, February 11, 2013, 07:41:11 PM

Previous topic - Next topic

manaw

ตอนนี้ต้องการใช้ POTRD 4 บิท เป็น Output ให้กับ 7 segment [ออกเป็น BCD ให้กับ CD4543] 
และที่เหลืออีก 4 บิท เป็นขาควบคุม digit 7 segment คะนั่งงมมา 4 ชม.และงงมั๊กมาก

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;
}

AnutSangka

ตรงกำหนด 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;

แบบนี้ครับ

manaw

แก้ตามที่บอกแล้วคะ ยังไม่ดีเลยคะ


AnutSangka

Quote from: manaw on February 11, 2013, 08:12:03 PM
แก้ตามที่บอกแล้วคะ ยังไม่ดีเลยคะ

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

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

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

อีกอย่างคือปรับเรื่องการ Delay ด้วยครับ delay_ms(1) นี่มันไวเกินครับตามนุษย์สังเกตไม่ทันหรอกครับ

manaw

คือเดิมทีใช้ทั้ง PORTD ไดร 7 segment อย่างเดี่ยวคะ ถ้าทำตามที่แนะนำก็ออกคะใช้การได้
แต่ตอนนี้ต้องการลดการใช้งาน PORT ลงโดยการใช้ทั้ง PORT ให้เป็นทั้ง Output แบบนี้คะ
       บิทที่ 0-3 เป็นการควบคุม digit ของ 7 segment
       บิทที่ 4-7 เป็น output ออกเป็น BCD เพื่อใช้กับ IC CD4543 คะขับ 7 segment คะ

JENG

//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;
}
สามารถติดตาม electoday ได้ที่

Facebook
www.facebook.com/groups/coopmicro

Google+
https://plus.google.com/communities/103482067769375459277

☺☺☺ความรู้ และความฉลาด ไม่ใช่สิ่งเดียวกัน จะมีประโยชน์อะไร ถ้าฉลาดแต่อยู่ในกะลา☺☺☺

manaw

อ่านดูแล้วไม่ค่อยเข้าใจเลยคะ งงมากเลย เพิ่งหักเล่นด้วย ลองเบิร์นดูแล้วเหมือนเดิม

samira

Quote from: AnutSangka on February 11, 2013, 08:13:49 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 นี้ แต่ มันขึ้นกับว่า ข้อมูลที่เอามาแสดง มันเปลียนเร็วหรือเปล่ามากกว่า

หวังว่า คงมีประโยชน์บ้าง
" If you're born poor, it's not your mistake. But if you die poor, it's your mistake"
Bill Gates.