550 likes | 822 Views
嵌入式 系統 training - HT32F175x275x. 袁世一 逢甲通訊系. Outline. Embedded system vs. … Clock Control GPIO – General purpose I/O Counter Interrupt AFIO – Alternate Function I/O. Embedded system vs. …. So, programming in Embedded system different from … care about special purposes
E N D
嵌入式系統 training- HT32F175x275x 袁世一 逢甲通訊系
Outline • Embedded system vs. … • Clock Control • GPIO – General purpose I/O • Counter • Interrupt • AFIO – Alternate Function I/O
Embedded system vs. … • So, programming in Embedded system different from … • care about special purposes • care about memory • care about HW considerations • care about COST
上課預計時程 *希望7/1進度可以提前,以增加7/3的程式說明時間
Clock control(7/1) • 基礎 ARM 時脈概念 • HT32F125x 時脈控制單元 (clock control unit, CKCU) • 範例程式
General ARM clock concept • 時脈是控制嵌入式系統動作同步的訊號 • ARM為:系統晶片SoC(System on Chip) • 許多功能區塊整合在IC內部 • 連在不同的Bus(匯流排)上,以提升IC效能 • 不同Bus可以使用不同的時脈 • Bus種類: 高/低速bus • AHB: High speed bus • APB: Low speed (Peripheral) bus
ARM 時脈種類 • HSI & LSI – High/Low speed Internal RC oscillator • HSI: • 系統預設時鐘,內部RC振盪 • 可以直接作為系統時鐘或作為PLL輸入(PLL=HSI/2) • 精度較差 • LSI: • 內部RC振盪 • 低功耗時脈源 • 可以在停機和待機模式下保持系統運做 • 提供看門狗和自動喚醒單元時脈 • HSE & LSE – High/Low speed External crystal • HSE:外部振盪器 • 提供非常精確的主時鐘 • LSE:低速外部晶體 • 一般專門用於RTC
PLL – phase lock loop(倍頻/除頻) • prescalers/multiplexers(倍頻/除頻設定) • System clock (CK_SYS) -> AHB/APB • gating(停止某些電路功能)
CKCU Registers 設定舉例 • Global Clock Configuration Register (GCFGR) • 32 bits • specifies clock source for PLL/USART/Watchdog Timer/CKOUT circuits • 使用C即可 • 如需深入了解,請見SPEC中Registers說明 CKCU_APBPerip0ClockConfig(CKCU_APBEN0_AFIO, ENABLE); CKCU_APBPerip0ClockConfig(BUTTON_GPIO_PIN, ENABLE);
GPIO – General purpose I/O(7/1) • ARM GPIO 架構 • ARMIO 控制
ARM GPIO architecture • 32個GPIO Pin • PA0~PA15 / PB0~PB15 • 其他功能腳位也可以分享GPIO port來增加功能的彈性 • 透過相關的組態暫存器的設定
GPIO控制 • 方向:輸入 OR 輸出 • 輸入腳位控制 • 弱拉升/弱拉降 • 輸出腳位控制 • 推拉式控制 OR 開汲極 • 推動電流強度 • 類比/數位 (AFIO控制)– 之後會說明 • 組態鎖定
RESET(或初供電)時GPIO之預設值 • 均為input • 無拉升/拉降電阻 (no pull-up/pull-down) • 例外: • PA9(拉降)、PA10 (拉升) 、PA13 (拉升) 、PA14 (拉升) • For boot/debug
GPIO Registers設定舉例 • Port A Data Direction Control Register (PADIRCR) • 32 bits • control the direction of the GPIO Port • 同時脈設定,使用C即可 • 如需深入了解,請見SPEC中Registers說明 GPIO_DirectionConfig(KEY1_BUTTON_GPIO_PORT, KEY1_BUTTON_GPIO_PIN, GPIO_DIR_IN); GPIO_DirectionConfig(LED1_GPIO_PORT, LED1_GPIO_PIN, GPIO_DIR_OUT);
程式範例 int main(void) { system_init(); while(1) { x = read_input_pin; write_output(x); } } while(1) { TmpStatus = GPIO_ReadInBit(WAKEUP_BUTTON_GPIO_PORT, WAKEUP_BUTTON_GPIO_PIN); GPIO_WriteOutBits(LED1_GPIO_PORT, LED1_GPIO_PIN, TmpStatus); TmpStatus = GPIO_ReadInBit(KEY1_BUTTON_GPIO_PORT, KEY1_BUTTON_GPIO_PIN); GPIO_WriteOutBits(LED2_GPIO_PORT, LED2_GPIO_PIN, TmpStatus); TmpStatus = GPIO_ReadInBit(KEY2_BUTTON_GPIO_PORT, KEY2_BUTTON_GPIO_PIN); GPIO_WriteOutBits(LED3_GPIO_PORT, LED3_GPIO_PIN, TmpStatus); } }
程式範例 int main(void) { … CKCU_APBPerip0ClockConfig(CKCU_APBEN0_AFIO, ENABLE); CKCU_APBPerip0ClockConfig(DVB_GpioClock[WAKEUP_BUTTON_GPIO_ID], ENABLE); … HT32F_DVB_GPxConfig(WAKEUP_BUTTON_GPIO_ID, WAKEUP_BUTTON_AFIO_PIN, WAKEUP_BUTTON_AFIO_MODE); … GPIO_DirectionConfig(WAKEUP_BUTTON_GPIO_PORT, WAKEUP_BUTTON_GPIO_PIN, GPIO_DIR_IN); … GPIO_InputConfig(WAKEUP_BUTTON_GPIO_PORT, WAKEUP_BUTTON_GPIO_PIN, ENABLE); … //5: 3 output pins … while(1) { … } } • system_init: • Enable APB clock • enable APB clock for 3 pins • connect 3 pins to GPIO function (Port, Pin, Func) • 3 pins’ GPIO as Input • enable 3 pins • same as 1-4 for 3 output pins • loop • x=read input • output x -> y • Too many codes • see code example
Practice • Target • 使用for, 控制LED閃爍 • 讀取按鈕值, 控制LED閃爍 • 按一次亮, 再一次暗 • 讀取按鈕值, 控制LED閃爍的開始/停止 • 按一次開始閃爍, 再一次停止閃爍
Counter(計數器)(7/2) • HT32Fx has 4 counters: • GPTM0/1: General Purpose Timer 0 & 1 • BFTM0/1: Basic Function Timer 0 & 1
Counter • This training uses BFTM0 • Two method: • loop method – this training • Interrupt method – next training • BFTM需要設定: • Counter Reg: up counter • Compare Reg: max value • Status Reg: Counter==Compare • Use C-lib
Counter loop programming • clock Init, LED(GPIO) Init • BFTM setting • max value • sysCLK: 1sec • sysCLK/2: 0.5sec • counter value (=0) • BFTM as OneShot • loop(1) • start BFTM (enable) • wait for BFTM.status change • toggle LED int main(void) { CKCU_APBPerip1ClockConfig(…); HT32F_DVB_LEDInit(LED2); BFTM_SetCompare(BFTM1, SystemCoreClock); BFTM_SetCounter(BFTM1, 0); BFTM_OneShotModeCmd(BFTM1, ENABLE); while (1) { BFTM_EnaCmd(BFTM1, ENABLE); while (BFTM_GetFlagStatus(BFTM1) != SET); BFTM_ClearFlag(BFTM1); HT32F_DVB_LEDToggle(LED2); } }
Counter programming • Interrupt counter control: • Training latter
Interrupt(7/2) • Interrupt concept • ARM NVIC • sample code
Interrupt concept • 中斷是一個訊號,會促使電腦改變其正常的運作流程。 • 在接收到來自外部硬體信號之後,CPU將進行相應的硬/軟體處理 • 發出的信號稱為中斷請求(interrupt request,IRQ) • IRQ導致CPU執行資訊切換(context switch)來保存執行狀態 • 中斷會將控制權轉換到中斷處理常式(Interrupt Service Routine, ISR) • 軟體中斷則為CPU指令集中的一個中斷指令
種類 • 狀態觸發 • 邊沿觸發 • 中斷向量表 • 中斷向量表包含數個中斷向量,每個向量包含中斷處理程序的起始地址
中斷處理過程 • 外部硬體信號發出IRQ • CPU結束執行上一個機械碼 • CPU同意中斷 • CPU儲存CPU執行狀態 • CPU取得中斷位址 • CPU執行ISR • ISR執行完成 • CPU取得中斷前CPU執行狀態 • CPU繼續執行原本程式
ARM NVIC • NVIC– Nested Vectored Interrupt Controller • Interrupt Number: 31 peripheral Int • Interrupt Types: • USART, SPI, I2C • Timer (BFTM, GPTM) • ADC, Comparator, • GPIO input • WakeUP signal, RTC, Low Vdd • Clock (HSE, HIS, LSE, LSI, PLL) • Priority: configurable, 16 levels NVIC_EnableIRQ(BFTM0_IRQn);
Counter Interrupt programming int main(void) { CKCU_APBPerip1ClockConfig(…); HT32F_DVB_LEDInit(LED1); NVIC_EnableIRQ(BFTM0_IRQn); BFTM_SetCompare(BFTM0, SystemCoreClock/2); BFTM_SetCounter(BFTM0, 0); BFTM_IntConfig(BFTM0, ENABLE); BFTM_EnaCmd(BFTM0, ENABLE); while (1) { } } • clock Init, LED(GPIO) Init • BFTM_INT unmask • BFTM setting • max value • sysCLK: 1sec • sysCLK/2: 0.5sec • counter value (=0) • BFTM Interrupt enable • begin BFTM • loop(1) do_nothing(); //in ht32f…_it.c: // Interrupt service routing (ISR): void BFTM0_IRQHandler(void) { HT32F_DVB_LEDToggle(LED1); BFTM_ClearFlag(BFTM0); }
AFIO – Alternate Function I/O(7/3) • 擴大GPIO 的靈活性 • GPIO外設功能 • 每個GPIO腳 • 配置為有四個不同的功能(設置GPxCFGR暫存器) • 根據IP 資源的使用情況和應用需求,可以使用週邊I/O 映射機制來選擇合適的功能
Example: ADC • Set AFIO to ADC • Set ADC to get Analog data from potentionmeter(電位計)
HT32FADC 特性 • 12-bitADC • Sample rate: Up to 1 uS/S • 8 external channels • 2 int_ref_voltage:Vssa & Vdda • sampling time for each channel • Three conversion modes • One shot • Continuous • Discontinuous • 8 dedicated sequencers and data registers • Triggered by • Software • external interrupt • GPTM (MTO and PWM CHnO) • Interrupts for ... • Single conversion end • Subgroup conversion end • Cycle conversion end • Analog Watchdog • Data register overwrite
Function descriptionsConfiguration • ADRST [0] = 1: ADC reset • Clock setup: • CK_ADC = APB_PCLK • ADC Trigger • ADCTCR (Trigger Control Registers) • ADTM = ADCTCR[2]: GPTM enable • ADEXTI = ADCTCR[1]: EXTI enable • ADSW = ADCTCR[2]: SW enable • ADCTSR (Trigger Source Registers) • GPTME = ADCTSR[26:24]: GPTM Event selection (all at rising edge_ • 0: GPTM MTO • 1-4: CH0-CH3 • GPTMS = ADCTSR[18:16] GPTM selection • 2/3 = GPTM0/GPTM1 • ADEXTIS = ADCTSR[11:8] : EXTI line selection • 0-F: EXTI line 0-15 • ADSC = ADCSTR[0]: • set: SW Event begin once • reset: automatic when this ADC complet
Data save register • ADCDRn (n=0-7) • flag ADVLDn goes to 1, automatically , if ADCDRn is valid • flag ADVLDn goes to 0, automatically, if ADCDRn is read • if ADCDRn not read and overwrited by another ADC round, ADIAWO of ADCIRAW = 1 • Status Flags • ADIRAWO = ADCIRAW[24]: data register overwrite error • ADIRAWS = ADCIRAW[2]: register: single sample finish • ADIRAWG = ADCIRAW[1]: register: sub-group finish • ADIRAWC = ADCIRAW[0]: register: cycle (group) finish
Interrupt • ADIMASKO = ADCIMSK[24]: ADC Data overwrite INT mask • ADIMASKC = ADCIMSK[2]: cycle (group) finish INT mask • ADIMASKG = ADCIMSK[1]: sub-group finish INT mask • ADIMASKS = ADCIMSK[0]: single ADC finish INT mask • Trigger begin: • SW trigger: ADSC of ADCTSR (when start ADC, ADSC reset) • 5 GPTM trigger: MTO (master), 4 GPTM-CHn (n=0-3) • EXTInt trigger: • setup: ADEXIS register - EXTInt (n=0,1) • ADEXTI=1
Sample time: • ADSTn of ADCSTRn[7:0] (n=0-7): • sampling time of channel n • T_conv = Tsample + Tlat • (conversion time, sampling time, latency) • Tasmple = ADSTn + 1.5 cycle • minimum Tlat = 12.5 cycle • Example: • CK_ADC = 14MHz, ADSTn = 0 • Tconv = 1.5 + 12.5 = 14 cycles (=1us)
Turn off ADC: ADCEN reset • Interrupt setup • All flags are set by SW for clearing, and automatically reset by HW • ADCICLRO = ADCICLR[24]: ADC Data overwrite INT Clear • ADCICLRC = ADCICLR[2]: cycle (group) finish INT clear • ADCICLRG = ADCICLR[1]: sub-group finish INT mask clear • ADCICLRS = ADCICLR[0]: single ADC finish INT mask clear
Sample Code int main(void) { USART_Configuration(); //for PC Enable_ADC_IRQ(); ADC_Clock_Enable(); AFIO_PIN6_SetTo_ADC(); ADC_Configure(ContinuousMode, 1 channel, sample rate, SW_trigger); ADC_enable(); begin_ADC(); while (1) { /* Output gPotentiometerLevel if needed. */ printf("\rPotentiometer level is %d %% ", (int)gPotentiometerLevel); } }
USART_Configuration void USART_Configuration(void) { USART_InitTypeDefUSART_InitStructure; USART_InitStructure.USART_BaudRate = 115200; USART_InitStructure.USART_WordLength = USART_WORDLENGTH_8B; USART_InitStructure.USART_StopBits = USART_STOPBITS_1; USART_InitStructure.USART_Parity = USART_PARITY_NO; USART_InitStructure.USART_Mode = USART_MODE_NORMAL; HT32F_DVB_COMInit(COM1, &USART_InitStructure); }
Enable_ADC_IRQ NVIC_EnableIRQ(ADC_IRQn);
ADC_Clock_Enable /* Enable peripheral clock of ADC */ CKCU_APBPerip1ClockConfig(CKCU_APBEN1_ADC, ENABLE); CKCU_APBPerip0ClockConfig(CKCU_APBEN0_AFIO, ENABLE); /* ADCLK frequency is set to 72/64 MHz = 1.125MHz */ CKCU_SetADCPrescaler(CKCU_PCLK_DIV64);
AFIO_PIN6_SetTo_ADC /* Config AFIO mode as ADC function */ AFIO_GPAConfig(AFIO_PIN_6 , AFIO_MODE_1);
ADC_Configure /* Continuous Mode, Length 1, SubLength 1 */ ADC_RegularGroupConfig(ADC, CONTINUOUS_MODE, 1, 1); /* ADC Channel 6, Rank 0, Sampling clock is (1.5 + 0) ADCLK Conversion time = (sampling clock + 12.5) / ADCLK = 12.4 uS */ ADC_RegularChannelConfig(ADC, ADC_CH_6, 0, 0); /* Use Software Trigger as ADC trigger source */ ADC_RegularTrigConfig(ADC, ADC_TRIG_SOFTWARE);