วันพฤหัสบดีที่ 5 มกราคม พ.ศ. 2566

STC15W408AS

    ไม่ถนัดที่จะใช้ 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 เข้ามากำหนดระยะห่าง

ไม่มีความคิดเห็น:

แสดงความคิดเห็น

MAPs

วันก่อนได้ลองเขียนแบบ แบบตัวนั้นมันต้องแนบแผนที่สังเขปของโครงการ ลองๆ แล้วก็ใช้ snazzymaps แล้วก็เอามาทำต่อใน inkscape มันก็ออกมาดูได้ระดับห...