ไม่ถนัดที่จะใช้ 8051 เพราะถนัดใช้แต่กับ Arduino IDE ไปหาหนังสือมาอ่าน ก็พอถูไถไปได้ ได้แต่ก็ไม่ดี ในอดีตก็เคยได้ลองกับพวก PIC16xx แต่ก็ไม่ได้อะไรเป็นชิ้นเป็นอัน ยิ่งนานวันยิ่งลืม
ตั้งแต่มีร้านออนไลน์จากจีน โลกโมดูลส่วนตัวก็เปลี่ยนไปเยอะ มีของเล่นต่างๆ มากมายก่ายกองให้เลือก ยังนึกถึงวันที่ซื้อหนังสือ+ชิพของไทย ราคาเกือบพัน เพราะเหตุนี้ มันจึงไกลเกินเอื้อมในการซื้อหามาเล่นได้เหมือนยุคนี้
แม้ว่ามันมีมานาน มันจะเป็นของโบราณ แต่มันก็ปรับปรุงอยู่เรื่อย อย่างเช่น ปรับมาเป็น single clock machine (1T) ตอนนี้ก็ยังถูกใช้งานอยู่ และยังไม่หายไปจากโลกนี้ มันต้องมีอะไรบางอย่างที่ดี อย่างน้อยราคาก็ถูก ในกล่องที่บ้านก็ยังมีอยู่ พวก 8051 มีทััง ATMEL, STC, WCH, NUVOTON งงตัวเองเลย ซื้อมาทำไม ไหนๆ ก็มีของแล้ว ก็คงต้องให้เวลาและลองใช้งานดู มีเป้าหมายก็แค่แก้เบื่อ
![]() |
Fig.1 STC15W408AS demo board cost 1.98USD (aliexpress) |
![]() |
Fig.2 STC15W401WS series. |
มี RC ในตัว ก็ประหยัดดี ซื้อมาประกอบเองก็ได้ จะว่าไป STM8S น่าใช้กว่า ถูกกว่าด้วย (0.7USD)
![]() |
Fig.3 STC15W408AS TSSOP20 pin map |
คู่มือของ STC มีตัวอย่างให้ดู ลองทำตาม
1) ลองทำ PWM ใช้ module2 (CCP2) ออกที่ขา P3.7
void main()
{
CCON = 0x00;
CMOD = 0x00; // 0:Sysclk /12 0x0E:Sysclk/8
CL = 0;
CH = 0;
CCAPM2 = 0x42;
PCA_PWM2 = 0x00;
CCAP2L = 0x00; //%Duty [ 0xFFFF - (CCAP2H<<8+CCAP2L) ] /0xFFFF
CCAP2H = 0x80;
CR = 1;
while(1);
}
![]() |
Fig.4 PWM 50% duty at 1.8kHz |
![]() |
Fig.5 DIV_CLK register |
ลองปรับความถี่ให้มันน้อยลง ต้องกำหนดใน register CLK_DIV
CLK_DIV = 0x07 // Sysclk /128
จะได้ความถี่น้อยลงมาเหลือ 14Hz ความถี่ระดับนี้ สังเกตุเห็นได้ด้วยตาเปล่า
![]() |
Fig.6 PWM with CLK_DIV= 0x07. |
2) Software Timer 16bit
ลองใช้งาน software timer และใช้ interrupt
void main()
{
//CLK_DIV = 0x04;
CMOD = 0x0D; //Sysclk/6 and ECF = 1
CCON = 0x00;
CL = 0x00;
CH = 0x00;
CCAPM2 = 0x48; //1001000B timer 16bit
CCAPM2 |= 0x01; //enable interrupt
CCAP2L = 0x00;
CCAP2H = 0x40;
CCON |= 0x40; //start timer CR = 1;
EA = 1;
while(1);
}
void PCA_isr() interrupt 7
{
CF = 0;
CCF2 = 0;
P10 = !P10; //sbit P10 = P1^0; Test OUTPUT
}
การคำนวณ
Sysclk 18432000Hz
Freq. = 18432000Hz / 6 / 0xFFFF = 46.88 Hz
T = 1 / f = 1 / 46.88 = 21.33ms
compare time ( CCAP2H<<8 + CCAP2L ) = 0x4000
Duty (0xFFFF - 0x4000) / 0xFFFF = (65535 - 16384) / 65535 = 0.75
Timer 21.33ms x 0.25 = 5.33ms
![]() |
Fig.7 Software timer while setting system clock 18.432MHz |
เอาไปทำ millis()
3) ADC
STC15408AS มี ADC 8Channel 10bit อยู่ที่ P1.0 -P1.7 ตามคู่มือจะมี register ที่เกี่ยวข้องหลายตัว
![]() |
Fig.8 ADC register |
จะเอา P1.x ไหนเป็น ADCx ก็ตั้งค่าใน P1ASF register โดยให้ bit นั้นเป็น 1
ถ้าให้ P1ASF = 0x01; ให้ P1.0 เป็น ADC0
P1ASF = 0x02; //0b00000010 ให้ P1.1 เป็น ADC1
ADC_CTR register เป็นตัวควบคุม ADC ต้องกำหนด sampling rate และเลือก ADCx ไหนที่จะทำ conversion ซึ่งมันจะทำทีละขา ทำเสร็จมันก็เก็บค่าไว้ใน ADC_RES, ADC_RESL จากนั้นจะเอาค่าไปทำไรก็ตามสะดวก
CLK_DIV นอกจากจะเอาไว้ทำตัวหารความถี่แล้วยังเอาไว้กำหนดการจัดเรียงข้อมูลค่า ADC_RES
กำหนดบิท ADRJ = 1 จะชิดขวา ส่วน ADRJ = 1 ชิดซ้าย
IE Interrupt Enable กำหนด EA, EADC เมื่อทำ conversion เสร็จจะให้ interrupt หรือไม่ ก็ควรเปิดการใช้งาน เพราะระหว่างการ conversion จะได้ทำอย่างอื่น เมื่อเกิด interrupt ขึ้นมา ก็ reset flag ซะเลย
void main(){
P1ASF = 0x02; //Select ADC1 P1.1 pin
CLK_DIV = 0x20;
ADC_RES = 0; //reset value
ADC_RESL = 0; //reset value
ADC_CONTR = 0xC0; //1100000B, Active ADC 180 clock cycle
ADC_CONTR |=0x01; //Conversion at ADC1 (P1.1)
ADC_CONTR |=0x08; //Start convertion, ADC_START = 1
EA = 1;
EADC = 1;
while(1);
}//end main
void ADC_isr() interrupt 5 using 1
{
ADC_CONTR &= !ADC_FLAG;
SendByte(ADC_RES); //ส่งค่าออกไปทาง serial *ต้องสร้างฟังก์ชั่น SendByte()
SendByte(ADC_RESL);
ADC_RES = 0; //reset value
ADC_RESL = 0; //reset value
ADC_CONTR = 0xC1; //1100001B, Active ADC 180 clock cycle at P1.1
ADC_CONTR |=0x08; //Start conversion, ADC_START = 1
}//end ADC ISR
![]() |
Fig.9 ADC conversion value. |
ผลการทำงาน มันทำงานเร็วมาก ควรใช้ timer หรือว่า delay เข้ามากำหนดระยะห่าง
ไม่มีความคิดเห็น:
แสดงความคิดเห็น