แล้วก็ไม่รู้จะช่วยยังไงด้วย
เริ่มจาก ทำความเข้าใจกับเรื่องต่างๆก่อน นะ
เขียน C ไม่เป็นทำไงดีวะ ? ก็เห็นหลายๆคนก็เขียน c ไม่เป็นอ่ะนะ
เลยจะมา เปรียบเทียบ C กะ Java(ที่เคยเขียนกัน) ว่ามันเหมือน รึ ต่างกันยังไง
- main
[c version]
int main(void){ // ที่จริง int, void ที่ตั้งค่าของ main เราก็ไม่ค่อยรู้หรอก ก๊อปๆมาเฉบๆ =.=[java version]
// do it
return 0;
}
public class test{- switch case, if, while, for ใช้เหมือนกันเลย (รวมทั้งการประกาศตัวแปรด้วย)
public static void main(String[] args){
//do it
}
}
- การเขียน Method (หรือ function)
[c version]
[ตัวที่ return] [ชือ function] ( [parameter] ){[java version]
//.....
return [ค่าที่คืน];
}
public [ตัวที่ return] [ชือ function] ( [parameter] ){จะเห็นว่า มันแทบไม่ต่างกันเลยนะ.... :D
//.....
return [ค่าที่คืน];
}
ประกาศตัวแปรใน AVR? บางคนอาจเห็น code ที่ว่า
int a, unsigned int b, char c, unsigned char d;
ก็อาจงงว่า ทำไมต้องเป็นงี้, unsigned มันคือบ้าอะไร
ผมขอตอบตรงๆว่า "ผมก็ใช้มั่วครับ =_= " แต่จะอธิบายคร่าวๆในแต่ละตัวแปรละกัน
ใน AVR นี้ ขอแนะนำให้ใช้ unsigned char นะ(ความรู้สึก) เพราะ char มั้นเป็นค่าแบบ 8 bit
และ unsigned หมายความว่าจะเป็นเฉพาะค่าบวก
เพราะฉะนั้น unsigned char จะเก็บค่าได้ตั้งแต่ 0-255 (เท่าที่เข้าใจนะ - -a)
Include? เหมือน import ใน java แหละ... ถ้าเราจะใช้อะไรก็ต้อง import เข้ามา
จริงๆ เราก็ไม่เคยจำหรอก ก๊อปๆ code เก่ามาอีกทีอ่ะ
- avr/io.h // จะมีตัวแปรต่างๆ ของ AVR อยู่,เอาไว้ตั้งค่าต่างๆ
- util/delay.h // สามารถใช้ _delay_ms(int ms); ได้....
- avr/interrupt.h // ใช้พวก interrupt
Input&Output? ขอสรุปง่ายๆ นะ
การตั้งค่า port ต่างๆของ avr นั้นจะตั้งค่าอยู่ที่ DDRx [x : B,C,D แล้วแต่เราจะใช้]
โดย DDR แต่ละตัวจะมีจำนวน bit ต่างกันไป
DDRB, DDRD จะมีจำนวน 8 บิท [7..0]
DDRC จะมี 7 บิท [6..0]
แล้วก็ ถ้าสมมติเราจะ set ให้ PORTB5 เป็น Output สามารถตั้งค่าดังนี้
DDRB |= (_BV(5)); // หมายถึง Shift left มา 5 บิทถ้าจะตั้งเป็น input ก็ตั้งดังนี้ (ไปดูในส่วนของ Switch ด้วยนะ)
DDRB &= ~(_BV(5));
Switch? ทำความเข้าใจกะ Switch ก่อนว่า ตอนต่อน่ะ มันจะเป็น Switch เปิด-ปิด
ถ้าเกิดกด Switch มันจะให้ค่า 0 ออกมา(ต่อลง Ground)
ฉะนั้น เราก็ต้อง Pull-up วงจร ซึ่ง AVR มัน Pull-up ให้อยู่แล้ว
(โดย set MCUCR ให้ bit ของ PUD ให้เป็น 0, ดูได้จาก datasheet หน้า 86)
แล้วก็ไปตั้งให้ PULL-UP เป็นค่า 1 ใน bit ที่ต้องการ
สมมติ จะ Pull-up PB0 ก็
DDRB &= ~(_BV(PB0));ส่วนการนำ Switch ไปใช้งานก็ทำได้ดังนี้// input PB0
PORTB |= _BV(PB0)// Pull-up PB0
if((PINB&0x01) == 0){ // เช็คว่าเป็น 0 รึยัง ???
_delay_ms(2); // delay ระหว่างการกดให้มันรอซักหน่อย...
........ // ทำอะไรก็ทำ... :P
}
Timer&Clock? มาเข้าใจก่อนว่า AVR ที่เรากำลังใช้อยู่นี้มันสามารถสร้าง Clock ที่ความถี่ 16MHz หรือใน 1 วิจะสร้าง clock ได้ 16 ล้านลูก... โดยเราสามารถลดจำนวน clock ที่ผลิตออกมาได้โดยการ prescale
(ดูได้ที่ datasheet หน้า 104 ตาราง prescale)
ถ้าเราต้องการให้มัน prescale ที่ 1024
TCCR0B |= _BV(CS02) | _BV(CS00)มันจะเปลี่ยนให้ AVR ปรับ Clock เป็นความถี่ 16MHz/1024 = 15625 Hz
แล้วก็ใน AVR จะมี Register ของ Timer อยู่คือ TCNT0( 8 bit )
ซึ่งทุกๆ clock TCNT0 จะนับค่าเพิ่มขึ้น 1 ไปเรื่อยๆ จนถึงค่า 255 แล้วปรับเป็น 0 ใหม่
Interrupt? เอาแบบสรุปๆ รวดเร็วเลยนะ...
การตั้งค่า Interrupt มีหลากหลายแบบ
เช่น Compare A, Compare B, Overflow
แต่ที่ใช้กันในการทำแลปคือ Interrupt Overflow Flag
ซึ่งตั้งค่าดังนี้ (ลองไปดู datasheet เกี่ยวกับ register timer เอาเด้อ... )
TIMSK0 |= _BV(TOIE0)ซึ่งการ Interrupt ทุกๆครั้งที่ TCNT0 นั้นเกิดการ Overflow(เกินค่า TOP ของ Counter)// Timer Overflow Interrupt Enable
sei(); //Enable Interrupt
จะเกิด Overflow flag ขึ้นและไปทำงานที่ ISR(TIMER0_OVF_vect)
ISR(TIMER0_OVF_vect) {
// สมมติว่า AVR ให้ clock ที่ 15625 Hz และ Counter นี้จะ Interrupt ทุกๆ 256 clock
// แสดงว่า Function นี้จะทำงาน 15625/256 ~ 61 Hz
}
PWM? ไปอ่านอันเก่าเอาเด้อ... =___= Click
ปล. ถ้าว่าง(มาก) + ไม่เบื่อล่าแย้... จะมาอธิบาย แต่ละ Lab ให้ละกัน =..=
ปล2. _BV(int bit) มันคือ shift left นะ.... ในBlog นี้ใช้ < < แล้วมันเจ๊ง = ="



