اهلا وسهلاً اخي ennng
كلامك صحيح الكثير يعتمد على المكتبات الجاهزة, والسبب لعدم توفر دروس بااللغة العربية تشرح طريقة ضبط جميع الاعدادات المستخدمة في الدوال .بس ان شااءالله راح احاول اشرح الي اعرفه ونفيد ونستفيد جميعاً.
ايضاً اخي ليس مطلوب التعامل مع الاسمبلي للتعامل مع الريجسترات,,انا استخدم برنامج mplab ومرفق معه الhi tech compiler ...واستخدم لغة السي للبرمجة. واذا كنت ترغب بعمل داله لاي خاصية ISP,I2c,USART,PWm..etc
لازم تقرا الداتا شيت..لانه موضحه كل شي بالتفصيل...فمثلا خلينا نشوف الخطوات التاليه لتفعيل خاصية ال pwm مكتوبه في الداتا شيت لل pic16f1937 صفحة 196:
19.5.7 SETUP FOR PWM OPERATION
The following steps should be taken when configuring
the CCP module for PWM operation:
1. Disable the PWM pin (CCPx) output driver(s) by
setting the associated TRIS bit(s).
2. Load the PRx register with the PWM period value.
3. Configure the CCP module for the PWM mode
by loading the CCPxCON register with the
appropriate values.
4. Load the CCPRxL register and the DCxBx bits of
the CCPxCON register, with the PWM duty cycle
value.
5. Configure and start Timerx:
• Clear the TMRxIF interrupt flag bit of the PIRx
register. See Note below.
• Configure the TxCKPS bits of the TxCON
register with the Timerx prescale value.
• Enable Timerx by setting the TMRxON bit of
the T2CON register.
6. Enable PWM output pin:
• Wait until Timerx overflows, TMRxIF bit of the
PIR1 register is set. See Note below.
• Enable the PWM pin (CCPx) output driver(s) by
clearing the associated TRIS bit(s).
|
وهذا الكود كتبته متبع نفس الخطوات لدقه 10 بت:
كود:
#include <htc.h>
__CONFIG(FOSC_INTOSC&WDTE_OFF&MCLRE_ON&CP_OFF);
#define _XTAL_FREQ 16000000
void main (void)
{
OSCCON = 0x7A; //select internal osciallator =16Mhz
__delay_us(4); //allow the new clock to stabilize
TRISCbits.TRISC2 =1; //disable pwm pin
RC2=0; //clear CCP1
PR2=0xff; // load 255 to PR2
CCP1M0=0; // sets CCP1CON in PWM mode
CCP1M1=0;
CCP1M2=1;
CCP1M3=1;
C1TSEL0= 0; //CCP1 is based off Timer 2 in PWM Mode
C1TSEL1= 0;
CCPR1L=0; //starts with 0% duty cycle
TMR2IF=0; //clear timer 2 flag
T2CKPS0=0; //Prescaler is 1
T2CKPS1=0;
TMR2ON= 1; //Turn on timer2
TMR2=0; //clear timer2
TRISCbits.TRISC2 =0; //enable and turn on PWM(CCP1)
while (1){
for(int dc = 0 ; dc < 255; dc++)
{
CCPR1L = dc ;
__delay_ms(100) ;
}
for(int dc = 0 ; dc < 256; dc++)
{
CCPR1L = 255- dc ;
__delay_ms(100) ;
}
}
}
ممكن تشوفه معقد في البداية بس حاول تقرا الداتا شيت وتقرا الكود مره واثنين وان شاءالله راح تتضح الامور وتكون سهلة ان شاءالله. نقطة اخيرة,, انا في الكود المكتوب في الاعلى مستخدم دقة 10 بت,وتستطيع استخدام المعادلة للتاكد. ولكن هل لاحظت ايضا في الكود اني اغير ال duty cycle من 0 الى 255. المفروض تكون من 0 الى 1023 ؟؟ السبب ان الميكروكنترول يعمل على 8 بت, بمعنى اخرى ان كل ريجستر يحتوي فقط على 8 بت. ولكن عند ضبط ال pwm على 10 بت, يقوم البيك باستخدام ريجستر كامل يسمى CCPR1L وهذا يوجد فيه 8 بت.. وريجستر اخر يسمى CCPR1H يوجد فيه ال 2 بت المتبقية.
ال CCPR1H يوجد فيه ال LSB (2^0 , 2^1
|0^2| 1^2|
اما ال CCPR1L يوجد فيه باقي ال 8 البت كالتالي:
|2^2| 3^2|4^2|5^2|6^2|7^2|8^2|9^2|
في الكود الي كتبته انا لم اغير قيمة ال CCPR1H اذا قيمتها الافتراضية صفر..ولكن قمنا بتغيير قيمة CCPR1L من 0 الى 255
بمعنى اخر ان القيمة النهائية سوف تكون مجموع ال CCPR1H و CCPR1L
فمثلاً:
صفر ديوتي = 00 0000 0000
50% ديوتي =00 0000 1000 ( لاحظ غيرنا فقط اخر 8 بت وهي تساوي 128 ولكن عند جمعها في عشره بت تكون القيمة 512)
100% ديوتي= 00 1111 1111 ( هنا نلاحظ اخر ثمنية بت تمثل 255 , و مجموع العشره بت 1020 وليس 1023) ولكن استطيع الحصول على 1023 عن طريق وضع قيمة ال CCPR1H= 3. ولكن هل تعلم 1020 كما تساوي في مخرج الى pwm ؟؟
|
PWM output = (5*1020)/1024=4.98V
|
اذا تقريباً 5 فولت
واغلب الاكواد المستخدمه لدقة عشرة بت تستخدم نفس الطريقة (تغيير قيمة الى CCPR1L فقط).
ولدقة 8 بت..نستخدم 2 بت من ريجستر CCP1H وتكون LSB و6 بت من ريجستر CCP1L وتكون ال MSB
CCP1L CCP1H
|0^2|1^2| |2^2|3^2|4^2|5^2|6^2|7^2|
صفر ديوتي = 00 0000 00
50% ديوتي = 00 1111 01 (اخر 6 بت تمثل 32 ومجموع ال 8 بت تمثل 124)
100% ديوتي = 00 1111 11 ( اخر 6 بت 64 ومجموع ال 8 بت تمثل 252)
ال 50% ديوتي في ال 8 بت تعطي قيمة 2.4 فولت 256/(124*5)
وال 10% ديوتي في ال 8 بت تعطي 4.92 فولت 256/(252*5)
وكما ذكرت يمكن الحصول على دقة عاليه بتغيير قيمة ال CCP1H وليس فقط ال CCP1L.
اسف على الاطالة ولكن احببت ان افصل اكثر حتى تتضح الفكرة بشكل اوضح.