Main Menu
Menu

Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Show posts Menu

Messages - crywolf

#185
ต้องการหาค่า RMS ของสัญญาณ Sine ความถี่ 50 Hz ใช่มั้ยครับ
ตอนนี้อย่าเพิ่งไปสนใจ สัญญาณ Input ครับ เอาเป็นว่า Config ยังไงให้ ADC ใช้งานได้ก่อน
Interrupt ยังไม่ต้องใช้ครับ เอา Polling ให้รอดก่อน
เริ่มจาก กำหนด CLK ให้ ADC ก่อนครับ
   RCC_ADCCLKConfig(RCC_PCLK2_Div6);
เสร็จแล้วก็ Enable Clock ให้กับ ADC และ PORT ซะ
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOC, ENABLE);
Config Port ให้เป็น Analog Input
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
    GPIO_Init(GPIOC, &GPIO_InitStructure);

Config ค่าต่างๆให้ ADC
   ADC_InitStructure.ADC_Mode = ADC_Mode_Independent
   ADC_InitStructure.ADC_ScanConvMode = DISABLE;
   ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
   ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
   ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
   ADC_InitStructure.ADC_NbrOfChannel = 1;
   ADC_Init(ADC1, &ADC_InitStructure);
   ADC_Cmd(ADC1, ENABLE);
   ADC_ResetCalibration(ADC1);
   while(ADC_GetResetCalibrationStatus(ADC1));
   ADC_StartCalibration(ADC1);
   while(ADC_GetCalibrationStatus(ADC1));

แล้วก็ลองอ่านค่า ADC มาโชว์ดูครับ โชว์ข้อมูลดิบๆก่อน ลองหา R ปรับค่าได้ มาลองต่อ เป็น Voltage Divider ดูก่อน
   While(1)
   {
      ADC_RegularChannelConfig(ADC1, ADC_Channel_14, 1, ADC_SampleTime_239Cycles5);
      ADC_SoftwareStartConvCmd(ADC1, ENABLE);
      while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);
      ADC_RAW_Value = ADC_GetConversionValue(ADC1);
   }
#186
ถ้าใช้ attiny 45 สามารถใช้ Software PWM ได้ครับ ได้ถึง 6 Channel
ลองดู Application Note (AVR136) ของ ATMEL นะครับ มีตัวอย่าง Code ด้วย
#187
มันออกแบบ PCB ง่ายกว่ามั้ง
ผมเป็นบ่อยครับ ออกแบบวงจรอย่างดิบดี พอไปออกแบบ PCB ลายมันเดินยาก
บางทีเดินลายแล้วมันไม่สวย ก็ต้องมาแก้วงจรกันใหม่เลย
#188
จากวงจรในรูป Code ที่ผมให้ไป น่าจะใช้ได้เลย และใช้ได้ถึง 4 หลัก ถ้าจะเอา 6 หลักก็เพิ่มได้ไม่ยาก

แต่แนะนำนิดนึงว่า ไม่ควรต่อ Common ของ 7-Segment เข้ากับขา Micro ตรงๆ
เพราะ ขาๆนึงของ Micro รับหรือจ่ายกระแสได้ไม่มาก การต่อตรงๆแบบนี้ ทำให้ ขา 1 ขา
ต้องขับ LED มากสุดถึง 7 ดวง (Segment) ควรใช้ Transistor หรือ Mosfet มาช่วย
#189
โค๊ดแบบมั่วๆ แต่คิดว่าน่าจะใช้ได้ ลองดูเป็นแนวทางได้

unsigned int msec=1000;
volatile unsigned char second=0, minute=0, hour=0;

static inline void InitTimers(void)
{
// Clear Timer on Compare or CTC mode and Prescaler of 64
TCCR0 |= 1<<WGM01|3<<CS00;
//Enable compare match interrupt
TIMSK |= 1<<OCIE0;
//Set compare value for 1 mSec
OCR0 = (F_CPU / 64 / 1000)-1;
//Enable global interrupts
sei();                 
}

int main(void)
{
DDRD = 0xff;

InitTimers();

while(1)
{
// PORTD |= 0x0F;
PORTD = ((second % 10)<<4)|0x0E;
_delay_ms(1);

// PORTD |= 0x0F;
PORTD = ((second / 10)<<4)|0x0D;
_delay_ms(1);

// PORTD |= 0x0F;
PORTD = ((minute % 10)<<4)|0x0B;
_delay_ms(1);

// PORTD |= 0x0F;
PORTD = ((minute / 10)<<4)|0x07;
_delay_ms(1);
}

return 0;
}

ISR(TIMER0_COMP_vect)
{
if(--msec == 0)
{
msec = 1000;

if(++second > 59)
{
second = 0;
if(++minute > 59)
{
minute = 0;
if(++hour > 23)
{
hour = 0;
}
}
}
}
}
#190
คิดง่ายๆก็คือ วงรอบของการนับจะคงที่อยู่ที่ 125 cycle คือ
ถ้าใน ISR มีคำสั่งอยู่น้อย เช่น 10  Cycle จะเหลือเวลาอีก 125-10 = 115 cycle เพื่อทำงานใน main
ถ้าใน ISR มีคำสั่งอยู่มาก เช่น 100  Cycle จะเหลือเวลาอีก 125-100 = 25 cycle เพื่อทำงานใน main
หรือใน ISR มีเงือนใขอยู่เยอะ ทำให้แต่ล่ะครั้งที่เข้า ISR จะใช้ เวลาไม่เท่ากัน ค่าเวลาที่เหลือเพื่อทำงานใน main ก็จะเปลี่ยนไปด้วย
แค่วงรอบของการ interrupt ก็ยังคงเท่าเดิมคือ 125 cycle
#191
ตอบท่าน samira ว่า ท่านไม่ต้องกังวลเรื่อง Overhead เพราะว่า

    Timer ใน CTC Mode จะนับอยู่ตลอดเวลา ในตัวอย่างคือ นับ 0..1..2..3..4..5......120..121..122..123..124..0..1..2....
และเมื่อนับ จาก 124..0 จะเกิด Interrupt ขึ้น และเมื่อกระโดดไปทำงานใน ISR ค่า Timer ก็นับไป เป็น 1
และเมื่อทำงาน Code ที่อยู่ใน Interrupt สมมุติว่า ทำไป 13 Cycle ค่า Timer ก็จะเป็น 14
และ จะนับเป็น 15 เมือกระโดดกลับไปที่ main และจะนับไปจนถึง 124 และ จะเกิด interrupt อีกรอบ
หมายความว่า จะไม่มีรอยต่อของ Timer ในการนับ ทำให้ได้ค่าคงที่ ในการ interrupt ที่ 1 msec
ฉนั้นไม่ว่าจะ Interrupt กี่ครั้ง หรือ ใน ISR จะมี Code กี่บรรทัด ค่า Timer 1 วินาที่ ที่ต้องการก็ยังคงถูกต้อง
โดยไม่จำเป็นต้องชดเชยใดๆ
#192
ผิดหลายจุดเลยครับ

เช่น

   lcd_en_set();
   lcd_en_clr();

ซึ่ง lcd_en หลังจาก set แล้ว ควรหน่วงเวลา อย่างน้อย 500 nsec

ผมแนะนำว่า ให้ไปดู Timing Diagram ใน Datasheet ครับ
และจะเขียน Code ยังไงให้ได้สัญญาณตาม Timing Diagram