На примере микроконтроллера К1986ВЕ92QI (MDR32F9Q2I) и отладочной платы LDM-K1986BE92QI рассмотрим задание тактовой частоты, в соответствии с пунктом 14 спецификации на МК.
По умолчанию, в созданном проекте Keil, тактирование МК осуществляется от внутреннего RC генератора 8 МГц. Встроенные (внутренние) RC генераторы МК обладают низкой стабильностью частоты и могут использоваться только в самых нетребовательных приложениях, зато не требуют внешних кварцев или генераторов.
Приведем расшифровку некоторых используемых аббревиатур:
Требуемая тактовая частота МК и периферии настраивается в достаточно широких пределах с помощью делителей, умножителей и коммутаторов частот.
Минимальный код для тактирования МК от внешнего генератора HSE 8 МГц.
#include "MDR32F9Q2I.h" // Заголовок с наименованиями CMSIS
#define PIN_LED 3 // Номер вывода светодиода
#define PORT_LED MDR_PORTB // Порт светодиода
static void CPU_init (void){ // Включаем тактирование от внешнего генератора 8 МГц (HSE). Умножители и делители не используем
MDR_RST_CLK->HS_CONTROL = 0x01; // Вкл. HSE внешний генератор (8 Мгц) (п.14.7.3)
MDR_RST_CLK->CPU_CLOCK |= (2 << 0); // Источник для CPU_C1 = HSE (п.14.7.4)
MDR_RST_CLK->CPU_CLOCK |= (1 << 8);// Источник для HCLK = CPU_C3
}
static void init_GPIO(void){ // Инициализация порта
MDR_RST_CLK->PER_CLOCK |= (1 << 22); // Разрешение тактирования порта B (п.14.7.8)
PORT_LED->OE |= (1 << PIN_LED); // Вход или выход. 0 - вход, 1 - выход (п.16.1.2)
PORT_LED->ANALOG |= (1 << PIN_LED); // Аналог или цифра. 0 - аналоговый, 1 - цифровой (п.16.1.4) (п.4 т.2)
PORT_LED->PWR |= (1 << PIN_LED * 2); // Передатчик. 0 - отключен, 1 - медленный, 2 - средний, 3 - быстрый (п.16.1.7)
}
int main (void){
CPU_init(); // Запускаем тактирование от HSE. Если закомментировать эту строчку, то будет тактирование от HSI.
init_GPIO(); // Инициализация порта светодиода
while(1){
for(int i = 0; i < 100000; i++){} // Задержка
PORT_LED->RXTX ^= (1 << PIN_LED); // Инвертировать значение бита (п.16.1.1) Мигаем светодиодом
}
}
Пример тактирования на максимальную для МК К1986ВЕ92QI (MDR32F9Q2I) частоту 80 МГц от внешнего генератора 8 МГц (HSE)
#include "MDR32F9Q2I.h" // Заголовок с наименованиями CMSIS
#define PIN_LED 0 // Номер вывода светодиода
#define PORT_LED MDR_PORTB // Порт светодиода
static void CPU_init (void){ // Включаем тактирование от внешнего генератора 8 МГц (HSE). Умножители и делители не используем
MDR_RST_CLK->HS_CONTROL = 0x01; // Вкл. HSE внешний кварц (8 МГц) (п.14.7.3)
while(!(MDR_RST_CLK->CLOCK_STATUS & (1 << 2))); // Ждем пока HSE выйдет в рабочий режим (п.14.7.1)
MDR_RST_CLK->PLL_CONTROL = ((1 << 2) | (9 << 8)); // Вкл. CPU PLL | коэф. умножения = 10 (п.14.7.2)
while(!(MDR_RST_CLK->CLOCK_STATUS & (1 << 1))); // Ждем когда PLL выйдет в раб. режим (п.14.7.1)
MDR_RST_CLK->CPU_CLOCK = (
(2 << 0x00) // Источник для CPU_C1 = HSE (п.14.7.4)
| (1 << 0x02) // Источник для CPU_C2 = CPU PLL
| (0 << 0x04) // Предделитель для CPU_C3 = 1
| (1 << 0x08)); // Источник для HCLK = CPU_C3
MDR_RST_CLK->PLL_CONTROL |= (1 << 0); // Включить USB PLL (п.14.7.1)
MDR_RST_CLK->PLL_CONTROL |= (7 << 4); // Коэфициент умножения для USB PLL = 8 (п.14.7.1)
while(!(MDR_RST_CLK->CLOCK_STATUS & (1 << 0))); // Ждем пока USB PLL выйдет в рабочий режим (п.14.7.1)
}
static void init_GPIO(void){ // Инициализация порта
MDR_RST_CLK->PER_CLOCK |= (1 << 22); // Разрешение тактирования порта B (п.14.7.8)
PORT_LED->OE |= (1 << PIN_LED); // Вход или выход. 0 - вход, 1 - выход (п.16.1.2)
PORT_LED->ANALOG |= (1 << PIN_LED); // Аналог или цифра. 0 - аналоговый, 1 - цифровой (п.16.1.4) (п.4 т.2)
PORT_LED->PWR |= (1 << PIN_LED * 2); // Передатчик. 0 - отключен, 1 - медленный, 2 - средний, 3 - быстрый (п.16.1.7)
}
int main (void){
CPU_init(); // Запускаем тактирование от HSE. Если закомментировать эту строчку, то будет тактирование от HSI.
init_GPIO(); // Инициализация порта светодиода
while(1){
for(int i = 0; i < 1000000; i++){} // Задержка
PORT_LED->RXTX ^= (1 << PIN_LED); // Инвертировать значение бита (п.16.1.1) Мигаем светодиодом
}
}