一、ArduinoAPI移植
通過arduinoapi實(shí)現(xiàn)封裝,實(shí)現(xiàn)底層分離,支持arduino生態(tài),
通過固件庫模塊化外設(shè),由ArduinoAPI調(diào)用
參考FastShift的封裝方式,由于F403A固件庫升級(jí),底層需要重新封裝
一、通用定時(shí)器使用
1.計(jì)時(shí)
由圖可以看出AHB時(shí)鐘為240M
定時(shí)器時(shí)鐘為240M
時(shí)間計(jì)算
Tout= ((arr+1)(psc+1))/Tclk;
Tclk:TIM3的輸入時(shí)鐘頻率(單位為MHz)。
Tout:TIM3溢出時(shí)間(單位為us)。
例:計(jì)時(shí)1ms,輸入時(shí)鐘頻率為240MHz。
??arr = 239,psc = 999。
??Tout = ((arr+1)(psc+1))/Tclk = ((239+1) *(240+1))/240=1000(us)=1(ms)
void trm3_int_init(u16 arr, u16 psc)
{
/* enable tmr1 clock */
crm_periph_clock_enable(CRM_TMR3_PERIPH_CLOCK, TRUE);
tmr_base_init(TMR3, arr, psc);
tmr_cnt_dir_set(TMR3, TMR_COUNT_UP);
tmr_interrupt_enable(TMR3, TMR_OVF_INT, TRUE);
/* tmr1 overflow interrupt nvic init */
nvic_priority_group_config(NVIC_PRIORITY_GROUP_0);
nvic_irq_enable(TMR3_GLOBAL_IRQn, 1, 0);
/* enable tmr3 */
tmr_counter_enable(TMR3, TRUE);
}
void TMR3_GLOBAL_IRQHandler(void)
{
TMR3->ists = 0;;
lv_tick_inc(1);
}
1.
2.ETR外部時(shí)鐘計(jì)數(shù)
對(duì)于外部脈沖(方波)計(jì)數(shù),通用的方法為捕獲比較方式,由于項(xiàng)目對(duì)于脈沖的精度要求比較高,在快速搭建代碼測(cè)試過后,發(fā)現(xiàn)該方法并不能滿足需求,進(jìn)而尋求計(jì)數(shù)更為精確的方法----ETR計(jì)數(shù)。
定時(shí)器實(shí)際就是一個(gè)計(jì)數(shù)器
可選內(nèi)部、外部、內(nèi)部觸發(fā)輸入用作計(jì)數(shù)時(shí)鐘
即使用外部觸發(fā)ETR作為計(jì)數(shù)器觸發(fā)源
參考https://blog.csdn.net/u010650845/article/details/81781670
4.ArduinoAPI - timer
void Timer_SetInterrupt(TIM_TypeDef* TIMx, uint32_t Time, Timer_CallbackFunction_t Function)
{
uint16_t period = 0;
uint16_t prescaler = 0;
uint32_t clock = TIMER_GET_CLOCK_MAX(TIMx);
if(!IS_TMR_ALL_PERIPH(TIMx) || Time == 0)
{
return;
}
/*將定時(shí)中斷時(shí)間轉(zhuǎn)換為重裝值和時(shí)鐘分頻值*/
Timer_TimeFactorization(
Time,
clock,
&period,
&prescaler
);
/*定時(shí)中斷配置*/
Timer_SetInterruptBase(
TIMx,
period,
prescaler,
Function,
TIMER_PREEMPTIONPRIORITY_DEFAULT,
TIMER_SUBPRIORITY_DEFAULT
);
}
三、ADC
1.ADC初始化(非DMA)
/**
* @brief ADC 配置
* @param ADCx: ADC地址
* @retval 無
*/
void ADCx_Init(adc_type* ADCx)
{
adc_base_config_type adc_base_struct;
if(ADCx == ADC1)
{
crm_periph_clock_enable(CRM_ADC1_PERIPH_CLOCK, TRUE);
}
else if(ADCx == ADC2)
{
crm_periph_clock_enable(CRM_ADC2_PERIPH_CLOCK, TRUE);
}
else if(ADCx == ADC3)
{
crm_periph_clock_enable(CRM_ADC3_PERIPH_CLOCK, TRUE);
}
else
{
return;
}
/* select combine mode */
adc_combine_mode_select(ADC_INDEPENDENT_MODE);
adc_base_default_para_init(&adc_base_struct);
adc_base_struct.sequence_mode = FALSE;
adc_base_struct.repeat_mode = FALSE;
adc_base_struct.data_align = ADC_RIGHT_ALIGNMENT;
adc_base_struct.ordinary_channel_length = 1;
adc_base_config(ADCx, &adc_base_struct);
adc_resolution_set(ADCx, ADC_RESOLUTION_12B);
adc_ordinary_conversion_trigger_set(ADCx, ADC_ORDINARY_TRIG_TMR1CH1, ADC_ORDINARY_TRIG_EDGE_NONE);
adc_dma_mode_enable(ADCx, FALSE);
adc_dma_request_repeat_enable(ADCx, FALSE);
adc_interrupt_enable(ADCx, ADC_OCCO_INT, FALSE);
adc_enable(ADCx, TRUE);
while(adc_flag_get(ADCx, ADC_RDY_FLAG) == RESET);
/* adc calibration */
adc_calibration_init(ADCx);
while(adc_calibration_init_status_get(ADCx));
adc_calibration_start(ADCx);
while(adc_calibration_status_get(ADCx));
}
/**
* @brief 獲取 ADC 值
* @param ADCx: ADC地址
* @param ADC_Channel: ADC通道
* @retval 無
*/
uint16_t ADCx_GetValue(adc_type* ADCx, uint16_t ADC_Channel)
{
#if 0
adc_ordinary_channel_set(ADCx, (adc_channel_select_type)ADC_Channel, 1, ADC_SAMPLETIME_47_5);
adc_ordinary_software_trigger_enable(ADCx, TRUE);
while(!adc_flag_get(ADCx, ADC_OCCE_FLAG));
#endif
return adc_ordinary_conversion_data_get(ADCx);
}
2.ADC_DMA 規(guī)則通道掃描
通道注冊(cè)API
pinMode(PWR_FWD_L_Pin, INPUT_ANALOG_DMA);
pinMode(PWR_FWD_M_Pin, INPUT_ANALOG_DMA);
pinMode(PWR_RET_L_Pin, INPUT_ANALOG_DMA);
pinMode(PWR_RET_M_Pin, INPUT_ANALOG_DMA);
pinMode會(huì)調(diào)用ADC_DMA_Register
/**
* @brief 注冊(cè)需要DMA搬運(yùn)的ADC通道
* @param ADC_Channel:ADC通道號(hào)
* @retval 見ADC_DMA_Res_Type
*/
ADC_DMA_Res_Type ADC_DMA_Register(uint8_t ADC_Channel)
{
#if 1
/*初始化ADC通道列表*/
static bool isInit = false;
if(!isInit)
{
uint8_t i;
for(i = 0; i < ADC_DMA_REGMAX; i++)
{
ADC_DMA_RegChannelList[i] = 0xFF;
}
isInit = true;
}
/*是否是合法ADC通道*/
if(!IS_ADC_CHANNEL(ADC_Channel))
return ADC_DMA_RES_NOT_ADC_CHANNEL;
/*是否已在引腳列表重復(fù)注冊(cè)*/
if(ADC_DMA_SearchChannel(ADC_Channel) != -1)
return ADC_DMA_RES_DUPLICATE_REGISTRATION;
/*是否超出最大注冊(cè)個(gè)數(shù)*/
if(ADC_DMA_RegCnt >= ADC_DMA_REGMAX)
return ADC_DMA_RES_MAX_NUM_OF_REGISTRATIONS_EXCEEDED;
/*寫入注冊(cè)列表*/
ADC_DMA_RegChannelList[ADC_DMA_RegCnt] = ADC_Channel;
/*注冊(cè)個(gè)數(shù)+1*/
ADC_DMA_RegCnt++;
#endif
return ADC_DMA_RES_OK;
}
ADC_DMA_Init函數(shù)必須放到所有ADC_DMA引腳注冊(cè)完之后
/**
* @brief ADC DMA 配置 配置ADC和對(duì)應(yīng)DMA,固定ADC1 如果不需要DMA則使用ADCx_Init函數(shù)
* 需要放到初始化最后,或者所有ADC_DMA引腳注冊(cè)完之后
* @param 無
* @retval 無
*/
void ADC_DMA_Init(void)
{
uint8_t index;
dma_init_type dma_init_structure;
adc_base_config_type adc_base_struct;
/*CLOCK CONFIG*/
crm_periph_clock_enable(CRM_ADC1_PERIPH_CLOCK, TRUE);
crm_periph_clock_enable(CRM_DMA1_PERIPH_CLOCK, TRUE);
/*INTERUPT COFIG*/
nvic_irq_enable(DMA1_Channel1_IRQn, 0, 0);
/*DMA CONFIG*/
dma_reset(DMA1_CHANNEL1);
dma_default_para_init(&dma_init_structure);
dma_init_structure.buffer_size = ADC_DMA_RegCnt;
dma_init_structure.direction = DMA_DIR_PERIPHERAL_TO_MEMORY;
dma_init_structure.memory_base_addr = (uint32_t)ADC_DMA_ConvertedValue;
dma_init_structure.memory_data_width = DMA_MEMORY_DATA_WIDTH_HALFWORD;
dma_init_structure.memory_inc_enable = TRUE;
dma_init_structure.peripheral_base_addr = (uint32_t) (&(ADC1->odt));
dma_init_structure.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_HALFWORD;
dma_init_structure.peripheral_inc_enable = FALSE;
dma_init_structure.priority = DMA_PRIORITY_HIGH;
dma_init_structure.loop_mode_enable = TRUE;
dma_init(DMA1_CHANNEL1, &dma_init_structure);
dma_interrupt_enable(DMA1_CHANNEL1, DMA_FDT_INT, TRUE);
dma_channel_enable(DMA1_CHANNEL1, TRUE);
/*ADC CONFIG*/
adc_combine_mode_select(ADC_INDEPENDENT_MODE);
adc_base_default_para_init(&adc_base_struct);
adc_base_struct.sequence_mode = TRUE;
adc_base_struct.repeat_mode = TRUE;
adc_base_struct.data_align = ADC_RIGHT_ALIGNMENT;
adc_base_struct.ordinary_channel_length = ADC_DMA_RegCnt;
adc_base_config(ADC1, &adc_base_struct);
for(index = 0; index < ADC_DMA_RegCnt; index++)
{
adc_ordinary_channel_set(
ADC1,
(adc_channel_select_type)ADC_DMA_RegChannelList[index],
index + 1,
ADC_SAMPLETIME_41_5
);
}
adc_ordinary_conversion_trigger_set(ADC1, ADC12_ORDINARY_TRIG_SOFTWARE, TRUE);
adc_dma_mode_enable(ADC1, TRUE);
adc_enable(ADC1, TRUE);
adc_calibration_init(ADC1);
while(adc_calibration_init_status_get(ADC1));
adc_calibration_start(ADC1);
while(adc_calibration_status_get(ADC1));
}
兩種方式 :1 DMA完成中斷中再次軟件觸發(fā),實(shí)現(xiàn)循環(huán)采樣,中斷頻率較高
2 ADC_DMA_GetValue中軟件觸發(fā),需要獲取數(shù)據(jù)時(shí)才開啟采集
通過CONFIG_ADC_CIRCLE_ENABLE 進(jìn)行切換
void DMA1_Channel1_IRQHandler(void)
{
if(dma_flag_get(DMA1_FDT1_FLAG) != RESET)
{
dma_flag_clear(DMA1_FDT1_FLAG);
#if (CONFIG_ADC_CIRCLE_ENABLE == 1)
adc_ordinary_software_trigger_enable(ADC1, TRUE);
#else
dma_trans_complete_flag = 1;
#endif
}
}
/**
* @brief 獲取DMA搬運(yùn)的ADC值
* @param ADC_Channel:ADC通道號(hào)
* @retval ADC值
*/
uint16_t ADC_DMA_GetValue(uint8_t ADC_Channel)
{
int16_t index;
if(!IS_ADC_CHANNEL(ADC_Channel))
return 0;
index = ADC_DMA_SearchChannel(ADC_Channel);
if(index == -1)
return 0;
#if (CONFIG_ADC_CIRCLE_ENABLE == 0)
adc_ordinary_software_trigger_enable(ADC1, TRUE);
while(dma_trans_complete_flag == 0);
dma_trans_complete_flag = 0;
#endif
return ADC_DMA_ConvertedValue[index];
}
六、USB HID IAP
1.準(zhǔn)備好Bootloader和app
2.配置好時(shí)鐘,一定要打開USB
3.將生成的時(shí)鐘配置復(fù)制到bootloader和app對(duì)應(yīng)位置
設(shè)置正確才能正確識(shí)別HID設(shè)備,并且免驅(qū),否則無法識(shí)別usb
void system_clock_config(void)
{
/* reset crm */
crm_reset();
/* enable hext */
crm_clock_source_enable(CRM_CLOCK_SOURCE_HEXT, TRUE);
/* wait till hext is ready */
while(crm_hext_stable_wait() == ERROR)
{
}
/* config pll clock resource */
crm_pll_config(CRM_PLL_SOURCE_HEXT, CRM_PLL_MULT_15, CRM_PLL_OUTPUT_RANGE_GT72MHZ);
/* enable pll */
crm_clock_source_enable(CRM_CLOCK_SOURCE_PLL, TRUE);
/* wait till pll is ready */
while(crm_flag_get(CRM_PLL_STABLE_FLAG) != SET)
{
}
/* config ahbclk */
crm_ahb_div_set(CRM_AHB_DIV_1);
/* config apb2clk */
crm_apb2_div_set(CRM_APB2_DIV_2);
/* config apb1clk */
crm_apb1_div_set(CRM_APB1_DIV_2);
/* enable auto step mode */
crm_auto_step_mode_enable(TRUE);
/* select pll as system clock source */
crm_sysclk_switch(CRM_SCLK_PLL);
/* wait till pll is used as system clock source */
while(crm_sysclk_switch_status_get() != CRM_SCLK_PLL)
{
}
/* disable auto step mode */
crm_auto_step_mode_enable(FALSE);
/* update system_core_clock global variable */
system_core_clock_update();
}
4 設(shè)置bootloader和app的起始位置
bootloader
app
保持一致文章來源:http://www.zghlxwxcb.cn/news/detail-715036.html
5 使用IAP Programmer下載,地址要設(shè)置為app地址
文章來源地址http://www.zghlxwxcb.cn/news/detail-715036.html
到了這里,關(guān)于AT32固件庫外設(shè)使用,ArduinoAPI接口移植,模塊化的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!