มาขอแนะนำผู้เริ่มต้นใหม่ STM32F4 discovery โดยkeil บทที่2 system clock

Started by deejun, August 21, 2013, 10:15:18 AM

Previous topic - Next topic

deejun

มาขอแนะนำผู้เริ่มต้นใหม่ STM32F4 discovery โดยkeil บทที่2 system clock

1      สร้าง Floder ชื่อ Clock ขึ้นมา
2      ทำการเพื่ม File  system_stm32f4xx.c และ stm32f4xx.hไว้ใน Floder
3      ทำการสร้างโปรเจคใหม่ เลือก เบอร์ IC stm32f407VG และให้ ADD File startup_stm32f4.s
                                                    เข้ามาด้วย  เพื่อที่จะได้ไม่ต้องไปก๊อปมาจาก Lib st ให้ยุ่งยากอีก  ความสำคัญคือมันจะช่วยจัดการค่า
                                                    เบื้องต้นให้กับ IC ให้พร้อมรับการโปรแกรมและการทำงาน ถ้าไม่มี  MCU จะ compiler ไม่ผ่าน
4     เขียนCode และ save โปรเจคเป็นนามสกุล .C

http://waijung.aimagin.com/default8mhz.png    ดูที่ภาพและบล็อกเพื่อความเข้าใจที่ดีขึ้นครับ
http://waijung.aimagin.com/stm32f4xx_clocktree_zoom60.png
http://waijung.aimagin.com/stm32f40x_block_diagram.png
http://waijung.aimagin.com/stm32f41x_block_diagram.png

http://waijung.aimagin.com/amg_f4connect2_diagram.png

ใครที่ใช้   Math lab โปรแกรมแบบ GUI น่าจะชื่นชอบแบบนี้ครับ  ดีมากแนะนำ
เข้าไปดูเลยครับตามลิงค์

http://waijung.aimagin.com/adc_demo.png
http://waijung.aimagin.com/stm32f4_regulardac_demo_model.png
http://waijung.aimagin.com/digital_input_demo.png
http://waijung.aimagin.com/advance_pwm_demo.png


http://waijung.aimagin.com/waijunginstall01.png
http://waijung.aimagin.com/waijunginstall02.png
http://waijung.aimagin.com/waijunginstall03.png
http://waijung.aimagin.com/waijunginstall04.png
http://waijung.aimagin.com/waijunginstall05.png
http://waijung.aimagin.com/openstlinkutility.png
http://waijung.aimagin.com/stlink-connecttotarget.png
http://waijung.aimagin.com/stlinkfirmwareupdate.png


http://waijung.aimagin.com/  เป็นเว็ป  แนะนำที่ดีครับ  รายละเอียดดีมากลองเปิดอ่านดูแต่ละบทๆ






บางครั้งเราก็ใช้ #include "stm32f4xx.h" เอาตัวอ้างอิงมาใช้งานเพื่อสื่อความหมายให้กับโปรแกรม
เพราะถ้าเอาแต่ใช้ ลอจิก อย่างเดียวอาจทำให้ไม่รู้ว่าทำอะไรกับบิตตรงไหน มันคือบิตอะไรเราใช้รูปแบบจาก
ตัวincludeมาช่วยก็ดีครับ

/******************************************************************************/
/*                                                                            */
/*                         Reset and Clock Control                            */
/*                                                                            */
/******************************************************************************/
/********************  Bit definition for RCC_CR register  ********************/
#define  RCC_CR_HSION                        ((uint32_t)0x00000001)
#define  RCC_CR_HSIRDY                       ((uint32_t)0x00000002)

#define  RCC_CR_HSEON                        ((uint32_t)0x00010000)
#define  RCC_CR_HSERDY                       ((uint32_t)0x00020000)
#define  RCC_CR_HSEBYP                       ((uint32_t)0x00040000)
#define  RCC_CR_CSSON                        ((uint32_t)0x00080000)
#define  RCC_CR_PLLON                        ((uint32_t)0x01000000)
#define  RCC_CR_PLLRDY                       ((uint32_t)0x02000000)
#define  RCC_CR_PLLI2SON                     ((uint32_t)0x04000000)
#define  RCC_CR_PLLI2SRDY                    ((uint32_t)0x08000000)


*********************************************************************************

รีจีสเตอร์ที่สำคัญในโหมดนี้คือ
************************************ 
RCC_CR

RCC_PLLCFGR

RCC_CFGR

RCC_CIR

***************************************

#include"stm32f4xx.h"
void clock()
   {
    RCC->CFGR      =   RCC_CFGR_HPRE_DIV1|RCC_CFGR_PPRE1_DIV4|RCC_CFGR_PPRE2_DIV2 ;
                 RCC->CR        =   0;
                 RCC->CR       |=   RCC_CR_HSEON;  // ให้ HSE Xtal เป็น ฐานเวลาหลัก     
    while (!(RCC->CR & 0x00020000));//   รอเวลาให้  Xtal osc ทำงาน
                 RCC->PLLCFGR   =   (RCC_PLLCFGR_PLLQ_2|RCC_PLLCFGR_PLLQ_1|RCC_PLLCFGR_PLLQ_0
                                                 |RCC_PLLCFGR_PLLSRC_HSE);
                 RCC->PLLCFGR  |=   (RCC_PLLCFGR_PLLN_8 |RCC_PLLCFGR_PLLN_6 |RCC_PLLCFGR_PLLN_4);
                 // เซ็ทค่าความถี่ และตัวคูณต่าง  ดูข้อมูลใน  Ref-manual stm32f407xx
                 // หัวข้อการเซ็ทอัป system clock
                 RCC->CR       |=    RCC_CR_PLLON;      // สั่งให้ตัวคูณ PLL ทำงาน
                 while (!(RCC->CR & 0x02000000));      // รอจนกว่า PLL พร้อมทำงาน
                 FLASH->ACR     =    0x00000605;        // จัดเวลา Flash ROM is 5 Wait state
                 RCC->CFGR     |=    0x00000002;        //  เลือกสัญญาณหลัก System PLL On
                 while ((RCC->CFGR & 0x0000000F) != 0x0000000A); // รอระบบ Wait system Pll พร้อมทำงาน
                }
int main(void)
                    {
                      clock();  //เรียกใช้งานจัดระบบ
                 //  Code โปรแกรม ที่จะทำการเขียน
}

AppleIIe

น่าจะปักหมุดได้นะ จะได้หาง่ายๆ  คงต้อง copy เอา ขอบคุณท่าน deejun ครับ
"Stay Hungry, Stay Foolish"
จงกระหาย และ ทำตัวโง่ให้ตลอดเวลา
"Innovation distinguishes between a leader and a follower."
นวัตกรรมแยกผู้นำกับผู้ตามออกจากกัน

คนฉลาด...ต้องโง่เป็น คนโง่ไม่เป็น...จะไม่มีทางฉลาด



Irumi

  ผมพึ่งจะเริ่มต้น STM32 ครับ ตอนนี้ซื้อ Board STM32F401RE nucleo มาศึกษา
  พอดีสงสัยครับ  ทำไมต้องมีการ set ค่า FLASH->ACR     =    0x00000605;        // จัดเวลา Flash ROM is 5 Wait state
  ถ้าไม่มีคำสั่งนี้จะเกิดอะไรขึ้น
  ไม่แน่ใจจะมีคนตอบรึเปล่าเพราะ กระทู้ตั้งแต่ปี 2013
   
  ขอบคุณครับ

dec

Quote from: Irumi on August 01, 2019, 02:01:27 PM
  ผมพึ่งจะเริ่มต้น STM32 ครับ ตอนนี้ซื้อ Board STM32F401RE nucleo มาศึกษา
  พอดีสงสัยครับ  ทำไมต้องมีการ set ค่า FLASH->ACR     =    0x00000605;        // จัดเวลา Flash ROM is 5 Wait state
  ถ้าไม่มีคำสั่งนี้จะเกิดอะไรขึ้น
  ไม่แน่ใจจะมีคนตอบรึเปล่าเพราะ กระทู้ตั้งแต่ปี 2013
   
  ขอบคุณครับ

โดยปกติวงจร logic เมื่อเราป้อน input ไป วงจรต้องใช้เวลาเล็กน้อยในการส่งออก output ครับ
ซึ่ง flash memory ก็เป็นลักษณะเดียวกัน แต่ flash memory จะใช้เวลาที่ค่อนข้างนานครับ

เวลา controller จะ อ่านคำสั่งหรือข้อมูลจาก flash memory นั้น controller ก็จะส่ง address ของ
ข้อมูลที่ต้องการอ่านไปให้ flash ทาง address bus พอ flash ได้รับ address แล้ว flash จะส่งข้อมูล
กลับมาให้ทาง data bus ครับ แต่สัญญาณที่ flash ส่งกลับมา มันจะยังไม่เสถียรในทันที controller ต้องรอ
ไปซักระยะหนึ่งให้สัญญาณที่ flash ส่งกลับมาเสถียรก่อน แล้วจึงอ่านข้อมูลจาก data bus ครับ

และหน่วยของเวลาที่ controller มันจะจับเวลาได้มันก็มีแค่จำนวน pulse ของสัญญาณ clock นั้นแหละครับ
5 Wait state ก็หมายถึงรอ 5 Clock Tick ก่อนที่จะอ่านข้อมูลกลับมา

ระยะเวลา Wait state นี้มีหลายปัจจัยครับ หลักๆ 3 ปัจจัยก็คือ

1. เทคโนโลยีของ flash ถ้า flash memory ดีๆ ก็จะส่งสัญญาณให้เสถียรได้เร็ว
    เช่น flash memory ใน STM32H7 ครับ ความถี่ clock สูงถึง 480MHz แต่รอแค่ 2 wait state

2. ความถี่ clock ที่ใช้ในการสื่อสารกับ flash ซึ่งปกติช่วงเวลาที่รอให้สัญญาณเสถียรมันจะคงที่
    แต่ถ้าเราปรับความถี่ clock สูงขึ้น คาบเวลาในแต่ละ clock ก็จะน้อยลง ก็ต้องเพิ่มจำนวน wait state clock

        เช่น flash ต้องใช้เวลา 100ns เพื่อให้สัญญาณเสถียร ถ้าใช้ความถี่ clock ที่ 50MHz จะมีคาบเวลาอยู่ที่ 20ns ต่อ 1 clock
        ก็ต้องรออย่างน้อย 5 wait state ขึ้นไปถึงจะเพียงพอให้สัญญาณจาก flash เสถียร (5*20ns = 100ns)

        แต่ถ้าเราเพิ่มความถี่ clock ไปที่ 100MHz แทน คาบเวลาอยู่ที่ 10ns ก็ต้องรออย่างน้อย 10 wait state ขึ้นไป
        ถึงจะเพียงพอให้สัญญาณจาก flash เสถียร (10*10ns = 100ns)

3. ระดับแรงดันที่ใช้ในระบบ ถ้าแรงดันยิ่งสูงสัญญาณก็จะเสถียรเร็วขึ้นครับ

        ยกตัวอย่าง STM32F401RE ใน Datasheet หน้า 61 ตารางที่ 15
               ถ้าใช้ VDD = 1.8V และความถี่ Clock = 84MHz ต้องรอ 4 wait states ขึ้นไป
               ถ้าใช้ VDD = 3.3V และความถี่ Clock = 84MHz ต้องรอ 2 wait states ขึ้นไป


มาถึงตรงนี้ ก็น่าจะพอเดาได้แล้วว่า ถ้าไม่มีการ set ค่า wait state ให้ถูกต้องจะเกิดผลอะไรหรือไม่

ปกติแล้ว ถ้าผมจำไม่ผิด STM32 แทบทุกตัว จะเริ่มการทำงานด้วยการใช้แหล่งกำเนิดสัญญาณ Clock ภายใน
หรือที่เรียกว่า HSI ซึ่งจะมีความถี่อยู่ที่ 16MHz เสมอ และจะตั้ง wait states ไว้ที่ 0

เวลาที่เราจะทำการ Config Clock เพื่อเปลี่ยนแหล่งกำเนิดสัญญาณ Clock ใหม่ ให้สูงขึ้น เราต้องพิจารณาว่า
ความถี่ใหม่ที่จะใช้นี้ต้องเพิ่ม wait states รึเปล่า ถ้าต้องเพิ่ม wait states  เราต้องทำการปรับ wait states
ก่อนที่จะทำการเปลี่ยนแหล่งกำเนิดสัญญาณ Clock ของระบบ
ไม่เช่นนั้นทันทีที่เปลี่ยนแหล่งกำเนิดสัญญาณ Clock
คำสั่งต่อไปที่ controller ทำการ fetch มาจะผิดไปหมด แล้วก็จะไปจบที่ Hardfault

ถ้าปรับ wait states สูงเกินไป controller ก็ยังทำงานได้ปกติครับ แต่ controller จะเสียเวลาในการรอข้อมูลไปเปล่าๆ
ซึ่งดูเหมือนว่ามันจะน้อย แต่ controller มีการ fetch คำสั่งตลอดเวลา ใน 1 วินาที fetch เป็นล้านครั้ง เมื่อรวมเวลาที่เสียไปมันก็มากอยู่ครับ

Irumi

Quote from: dec on August 02, 2019, 03:07:31 AM
Quote from: Irumi on August 01, 2019, 02:01:27 PM
  ผมพึ่งจะเริ่มต้น STM32 ครับ ตอนนี้ซื้อ Board STM32F401RE nucleo มาศึกษา
  พอดีสงสัยครับ  ทำไมต้องมีการ set ค่า FLASH->ACR     =    0x00000605;        // จัดเวลา Flash ROM is 5 Wait state
  ถ้าไม่มีคำสั่งนี้จะเกิดอะไรขึ้น
  ไม่แน่ใจจะมีคนตอบรึเปล่าเพราะ กระทู้ตั้งแต่ปี 2013
   
  ขอบคุณครับ

โดยปกติวงจร logic เมื่อเราป้อน input ไป วงจรต้องใช้เวลาเล็กน้อยในการส่งออก output ครับ
ซึ่ง flash memory ก็เป็นลักษณะเดียวกัน แต่ flash memory จะใช้เวลาที่ค่อนข้างนานครับ

เวลา controller จะ อ่านคำสั่งหรือข้อมูลจาก flash memory นั้น controller ก็จะส่ง address ของ
ข้อมูลที่ต้องการอ่านไปให้ flash ทาง address bus พอ flash ได้รับ address แล้ว flash จะส่งข้อมูล
กลับมาให้ทาง data bus ครับ แต่สัญญาณที่ flash ส่งกลับมา มันจะยังไม่เสถียรในทันที controller ต้องรอ
ไปซักระยะหนึ่งให้สัญญาณที่ flash ส่งกลับมาเสถียรก่อน แล้วจึงอ่านข้อมูลจาก data bus ครับ

และหน่วยของเวลาที่ controller มันจะจับเวลาได้มันก็มีแค่จำนวน pulse ของสัญญาณ clock นั้นแหละครับ
5 Wait state ก็หมายถึงรอ 5 Clock Tick ก่อนที่จะอ่านข้อมูลกลับมา

ระยะเวลา Wait state นี้มีหลายปัจจัยครับ หลักๆ 3 ปัจจัยก็คือ

1. เทคโนโลยีของ flash ถ้า flash memory ดีๆ ก็จะส่งสัญญาณให้เสถียรได้เร็ว
    เช่น flash memory ใน STM32H7 ครับ ความถี่ clock สูงถึง 480MHz แต่รอแค่ 2 wait state

2. ความถี่ clock ที่ใช้ในการสื่อสารกับ flash ซึ่งปกติช่วงเวลาที่รอให้สัญญาณเสถียรมันจะคงที่
    แต่ถ้าเราปรับความถี่ clock สูงขึ้น คาบเวลาในแต่ละ clock ก็จะน้อยลง ก็ต้องเพิ่มจำนวน wait state clock

        เช่น flash ต้องใช้เวลา 100ns เพื่อให้สัญญาณเสถียร ถ้าใช้ความถี่ clock ที่ 50MHz จะมีคาบเวลาอยู่ที่ 20ns ต่อ 1 clock
        ก็ต้องรออย่างน้อย 5 wait state ขึ้นไปถึงจะเพียงพอให้สัญญาณจาก flash เสถียร (5*20ns = 100ns)

        แต่ถ้าเราเพิ่มความถี่ clock ไปที่ 100MHz แทน คาบเวลาอยู่ที่ 10ns ก็ต้องรออย่างน้อย 10 wait state ขึ้นไป
        ถึงจะเพียงพอให้สัญญาณจาก flash เสถียร (10*10ns = 100ns)

3. ระดับแรงดันที่ใช้ในระบบ ถ้าแรงดันยิ่งสูงสัญญาณก็จะเสถียรเร็วขึ้นครับ

        ยกตัวอย่าง STM32F401RE ใน Datasheet หน้า 61 ตารางที่ 15
               ถ้าใช้ VDD = 1.8V และความถี่ Clock = 84MHz ต้องรอ 4 wait states ขึ้นไป
               ถ้าใช้ VDD = 3.3V และความถี่ Clock = 84MHz ต้องรอ 2 wait states ขึ้นไป


มาถึงตรงนี้ ก็น่าจะพอเดาได้แล้วว่า ถ้าไม่มีการ set ค่า wait state ให้ถูกต้องจะเกิดผลอะไรหรือไม่

ปกติแล้ว ถ้าผมจำไม่ผิด STM32 แทบทุกตัว จะเริ่มการทำงานด้วยการใช้แหล่งกำเนิดสัญญาณ Clock ภายใน
หรือที่เรียกว่า HSI ซึ่งจะมีความถี่อยู่ที่ 16MHz เสมอ และจะตั้ง wait states ไว้ที่ 0

เวลาที่เราจะทำการ Config Clock เพื่อเปลี่ยนแหล่งกำเนิดสัญญาณ Clock ใหม่ ให้สูงขึ้น เราต้องพิจารณาว่า
ความถี่ใหม่ที่จะใช้นี้ต้องเพิ่ม wait states รึเปล่า ถ้าต้องเพิ่ม wait states  เราต้องทำการปรับ wait states
ก่อนที่จะทำการเปลี่ยนแหล่งกำเนิดสัญญาณ Clock ของระบบ
ไม่เช่นนั้นทันทีที่เปลี่ยนแหล่งกำเนิดสัญญาณ Clock
คำสั่งต่อไปที่ controller ทำการ fetch มาจะผิดไปหมด แล้วก็จะไปจบที่ Hardfault

ถ้าปรับ wait states สูงเกินไป controller ก็ยังทำงานได้ปกติครับ แต่ controller จะเสียเวลาในการรอข้อมูลไปเปล่าๆ
ซึ่งดูเหมือนว่ามันจะน้อย แต่ controller มีการ fetch คำสั่งตลอดเวลา ใน 1 วินาที fetch เป็นล้านครั้ง เมื่อรวมเวลาที่เสียไปมันก็มากอยู่ครับ

ขอบคุณ คุณ dec มากๆเลยครับ กระจ่างเลยครับ :)

JimmyGrape

เยี่ยมเลย อยากให้มี post ดีๆแบบนี้อีกมากๆ