เนื่องจาก CH32V003J4M6 มีจำนวนขาเพียง 8 ขาเท่านั้น เลยมีการใส่ function การทำงานของขาที่ทับซ้อนลงไปในขา ที่ 1 และ 8 เพื่อมี function ต่างๆที่จำเป็นครบถ้วนขายใน 8 ขา
ดังนั้นเวลาที่เราใช้งาน USART ที่เป็นค่าเริ่มต้นของโปรแกรมจะใช้ขา PD5/PD6 เป็นขา TX/RX ทำให้มีการส่งข้อมูลออกมาที่ขาที่ 8 เพราะมีการใช้งานรวมกัน หากเราดูตามเอกสารอ้างอิงที่ WCH ให้มา
จากภาพและตาราง จะเห็นว่าขาที่ 8 จะมี function ที่ทับซ้อนกัน เช่น GPIO / URX / UTX / SWIO ตามรูปด้านล่าง
หากเราดูที่ Code เริ่มต้นการทำงานอย่างง่ายๆ เช่นตัวอย่าง code ของ GPIO
/*********************************************************************
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
USART_Printf_Init(115200);
printf("SystemClk:%d\r\n",SystemCoreClock);
#include "debug.h"
vu8 val;
/*********************************************************************
* @fn main
*
* @brief Main program.
*
* @return none
*/
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
Delay_Init();
USART_Printf_Init(115200);
printf("SystemClk:%d\r\n",SystemCoreClock);
while(1)
{
}
}
#include "debug.h"
vu8 val;
/*********************************************************************
* @fn main
*
* @brief Main program.
*
* @return none
*/
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
Delay_Init();
USART_Printf_Init(115200);
printf("SystemClk:%d\r\n",SystemCoreClock);
while(1)
{
}
}
ในส่วนของ
USART_Printf_Init(115200);
USART_Printf_Init(115200);
ที่ทำหน้าที่เกี่ยวกับ USART ส่งข้อมูลไม่ว่าจะเป็น OUTPUT หรือ DEBUG ออกมา
/*********************************************************************
* @brief Initializes the USARTx peripheral.
* @param baudrate - USART communication baud rate.
void USART_Printf_Init(uint32_t baudrate)
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOD, &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = baudrate;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Tx;
USART_Init(USART1, &USART_InitStructure);
USART_Cmd(USART1, ENABLE);
/*********************************************************************
* @fn USART_Printf_Init
*
* @brief Initializes the USARTx peripheral.
*
* @param baudrate - USART communication baud rate.
*
* @return None
*/
void USART_Printf_Init(uint32_t baudrate)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOD, &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = baudrate;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Tx;
USART_Init(USART1, &USART_InitStructure);
USART_Cmd(USART1, ENABLE);
}
/*********************************************************************
* @fn USART_Printf_Init
*
* @brief Initializes the USARTx peripheral.
*
* @param baudrate - USART communication baud rate.
*
* @return None
*/
void USART_Printf_Init(uint32_t baudrate)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOD, &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = baudrate;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Tx;
USART_Init(USART1, &USART_InitStructure);
USART_Cmd(USART1, ENABLE);
}
ตรงส่วนที่กำหนดขาของ GPIO ที่กำหนดขา PIN GPIO_Pin_5 ซึ่งปกติถ้าคิดแบบทั่วไปเพียงเปลี่ยน จาก GPIO_Pin_5 เป็น GPIO_Pin_6 ก็ควรจะทำงานแล้ว…
แต่มันไม่สามารถทำงานได้ เพราะว่ามีค่า REGISTER กำหนดการทำงานอยู่ ต้องไปแก้ไขหรือเปิดการทำงานของ function สำรองในการเปลี่ยนขา หรือ สลับขาก่อน ซึ่งการที่จะเปลี่ยนหรือสลับขาได้ต้องไปดูเอกสารการใช้งานของ MCU CH32V003 ก่อนว่าต้องเปิดหรือตั้งค่าอะไรบ้าง
มีมาดูค่า REGISTER ที่จำเป็นที่จะต้องกำหนดค่า ตามตารางด้านล่าง bit ที่ 21 จะต้องมีการตั้งค่าให้ถูกต้องในการสลับขา
เมื่อไปดูในส่วนของ Code ที่กำหนดไว้จะเป็นค่าที่ define ไว้แล้ว และค่าที่เราต้องใช้ในการ Remap จากภาพด้านบน คือ ค่า 10 ที่ Remap TX/PD6, RX/PD5
เมื่อเทียบ Code ดูแล้วจะพบว่า ค่า จะได้ดังนี้
GPIO_PartialRemap1_USART1 = Remap [01]
GPIO_PartialRemap2_USART1 = Remap [10]
GPIO_FullRemap_USART1 = Remap [11]
ค่าที่ define ไว้ใน code
และค่า REGISTER นี้อยู่ในส่วนของ AFIO (alternate functions) หรือ function อื่นๆ ที่รวมของใน ขานั้นๆ จำเป็นที่จะตั้งเปิด clock ให้เดียวเพื่อใช้งาน function รอง เหล่านี้
ดังนั้นในส่วนของ code จะมี function ที่กำหนดค่านี้อยู่คือ GPIO_PinRemapConfig
/*********************************************************************
* @fn GPIO_PinRemapConfig
* @brief Changes the mapping of the specified pin.
* @param GPIO_Remap - selects the pin to remap.
* GPIO_Remap_SPI1 - SPI1 Alternate Function mapping
* GPIO_PartialRemap_I2C1 - I2C1 Partial Alternate Function mapping
* GPIO_PartialRemap_I2C1 - I2C1 Full Alternate Function mapping
* GPIO_PartialRemap1_USART1 - USART1 Partial1 Alternate Function mapping
* GPIO_PartialRemap2_USART1 - USART1 Partial2 Alternate Function mapping
* GPIO_FullRemap_USART1 - USART1 Full Alternate Function mapping
* GPIO_PartialRemap1_TIM1 - TIM1 Partial1 Alternate Function mapping
* GPIO_PartialRemap2_TIM1 - TIM1 Partial2 Alternate Function mapping
* GPIO_FullRemap_TIM1 - TIM1 Full Alternate Function mapping
* GPIO_PartialRemap1_TIM2 - TIM2 Partial1 Alternate Function mapping
* GPIO_PartialRemap2_TIM2 - TIM2 Partial2 Alternate Function mapping
* GPIO_FullRemap_TIM2 - TIM2 Full Alternate Function mapping
* GPIO_Remap_PA12 - PA12 Alternate Function mapping
* GPIO_Remap_ADC1_ETRGINJ - ADC1 External Trigger Injected Conversion remapping
* GPIO_Remap_ADC1_ETRGREG - ADC1 External Trigger Regular Conversion remapping
* GPIO_Remap_LSI_CAL - LSI calibration Alternate Function mapping
* GPIO_Remap_SDI_Disable - SDI Disabled
* NewState - ENABLE or DISABLE.
void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState)
uint32_t tmp = 0x00, tmp1 = 0x00, tmpreg = 0x00, tmpmask = 0x00;
tmpmask = (GPIO_Remap & DBGAFR_POSITION_MASK) >> 0x10;
tmp = GPIO_Remap & LSB_MASK;
if((GPIO_Remap & 0x10000000) == 0x10000000)
tmpreg &= ~((1<<1) | (1<<22));
tmpreg |= ~DBGAFR_SDI_MASK;
tmpreg |= (GPIO_Remap & 0xEFFFFFFF);
else if((GPIO_Remap & 0x80000000) == 0x80000000)
tmpreg &= ~((1<<2) | (1<<21));
tmpreg |= ~DBGAFR_SDI_MASK;
tmpreg |= (GPIO_Remap & 0x7FFFFFFF);
else if((GPIO_Remap & (DBGAFR_LOCATION_MASK | DBGAFR_NUMBITS_MASK)) == (DBGAFR_LOCATION_MASK | DBGAFR_NUMBITS_MASK))/* SDI */
tmpreg &= DBGAFR_SDI_MASK;
AFIO->PCFR1 &= DBGAFR_SDI_MASK;
tmpreg |= (tmp << ((GPIO_Remap >> 0x15) * 0x10));
else if((GPIO_Remap & DBGAFR_NUMBITS_MASK) == DBGAFR_NUMBITS_MASK)/* [15:0] 2bit */
tmp1 = ((uint32_t)0x03) << tmpmask;
tmpreg |= ~DBGAFR_SDI_MASK;
tmpreg |= (tmp << ((GPIO_Remap >> 0x15) * 0x10));
tmpreg &= ~(tmp << ((GPIO_Remap >> 0x15) * 0x10));
tmpreg |= ~DBGAFR_SDI_MASK;
tmpreg |= (tmp << ((GPIO_Remap >> 0x15) * 0x10));
/*********************************************************************
* @fn GPIO_PinRemapConfig
*
* @brief Changes the mapping of the specified pin.
*
* @param GPIO_Remap - selects the pin to remap.
* GPIO_Remap_SPI1 - SPI1 Alternate Function mapping
* GPIO_PartialRemap_I2C1 - I2C1 Partial Alternate Function mapping
* GPIO_PartialRemap_I2C1 - I2C1 Full Alternate Function mapping
* GPIO_PartialRemap1_USART1 - USART1 Partial1 Alternate Function mapping
* GPIO_PartialRemap2_USART1 - USART1 Partial2 Alternate Function mapping
* GPIO_FullRemap_USART1 - USART1 Full Alternate Function mapping
* GPIO_PartialRemap1_TIM1 - TIM1 Partial1 Alternate Function mapping
* GPIO_PartialRemap2_TIM1 - TIM1 Partial2 Alternate Function mapping
* GPIO_FullRemap_TIM1 - TIM1 Full Alternate Function mapping
* GPIO_PartialRemap1_TIM2 - TIM2 Partial1 Alternate Function mapping
* GPIO_PartialRemap2_TIM2 - TIM2 Partial2 Alternate Function mapping
* GPIO_FullRemap_TIM2 - TIM2 Full Alternate Function mapping
* GPIO_Remap_PA12 - PA12 Alternate Function mapping
* GPIO_Remap_ADC1_ETRGINJ - ADC1 External Trigger Injected Conversion remapping
* GPIO_Remap_ADC1_ETRGREG - ADC1 External Trigger Regular Conversion remapping
* GPIO_Remap_LSI_CAL - LSI calibration Alternate Function mapping
* GPIO_Remap_SDI_Disable - SDI Disabled
* NewState - ENABLE or DISABLE.
*
* @return none
*/
void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState)
{
uint32_t tmp = 0x00, tmp1 = 0x00, tmpreg = 0x00, tmpmask = 0x00;
tmpreg = AFIO->PCFR1;
tmpmask = (GPIO_Remap & DBGAFR_POSITION_MASK) >> 0x10;
tmp = GPIO_Remap & LSB_MASK;
if((GPIO_Remap & 0x10000000) == 0x10000000)
{
tmpreg &= ~((1<<1) | (1<<22));
tmpreg |= ~DBGAFR_SDI_MASK;
if(NewState != DISABLE)
{
tmpreg |= (GPIO_Remap & 0xEFFFFFFF);
}
}
else if((GPIO_Remap & 0x80000000) == 0x80000000)
{
tmpreg &= ~((1<<2) | (1<<21));
tmpreg |= ~DBGAFR_SDI_MASK;
if(NewState != DISABLE)
{
tmpreg |= (GPIO_Remap & 0x7FFFFFFF);
}
}
else if((GPIO_Remap & (DBGAFR_LOCATION_MASK | DBGAFR_NUMBITS_MASK)) == (DBGAFR_LOCATION_MASK | DBGAFR_NUMBITS_MASK))/* SDI */
{
tmpreg &= DBGAFR_SDI_MASK;
AFIO->PCFR1 &= DBGAFR_SDI_MASK;
if(NewState != DISABLE)
{
tmpreg |= (tmp << ((GPIO_Remap >> 0x15) * 0x10));
}
}
else if((GPIO_Remap & DBGAFR_NUMBITS_MASK) == DBGAFR_NUMBITS_MASK)/* [15:0] 2bit */
{
tmp1 = ((uint32_t)0x03) << tmpmask;
tmpreg &= ~tmp1;
tmpreg |= ~DBGAFR_SDI_MASK;
if(NewState != DISABLE)
{
tmpreg |= (tmp << ((GPIO_Remap >> 0x15) * 0x10));
}
}
else/* [31:0] 1bit */
{
tmpreg &= ~(tmp << ((GPIO_Remap >> 0x15) * 0x10));
tmpreg |= ~DBGAFR_SDI_MASK;
if(NewState != DISABLE)
{
tmpreg |= (tmp << ((GPIO_Remap >> 0x15) * 0x10));
}
}
AFIO->PCFR1 = tmpreg;
}
/*********************************************************************
* @fn GPIO_PinRemapConfig
*
* @brief Changes the mapping of the specified pin.
*
* @param GPIO_Remap - selects the pin to remap.
* GPIO_Remap_SPI1 - SPI1 Alternate Function mapping
* GPIO_PartialRemap_I2C1 - I2C1 Partial Alternate Function mapping
* GPIO_PartialRemap_I2C1 - I2C1 Full Alternate Function mapping
* GPIO_PartialRemap1_USART1 - USART1 Partial1 Alternate Function mapping
* GPIO_PartialRemap2_USART1 - USART1 Partial2 Alternate Function mapping
* GPIO_FullRemap_USART1 - USART1 Full Alternate Function mapping
* GPIO_PartialRemap1_TIM1 - TIM1 Partial1 Alternate Function mapping
* GPIO_PartialRemap2_TIM1 - TIM1 Partial2 Alternate Function mapping
* GPIO_FullRemap_TIM1 - TIM1 Full Alternate Function mapping
* GPIO_PartialRemap1_TIM2 - TIM2 Partial1 Alternate Function mapping
* GPIO_PartialRemap2_TIM2 - TIM2 Partial2 Alternate Function mapping
* GPIO_FullRemap_TIM2 - TIM2 Full Alternate Function mapping
* GPIO_Remap_PA12 - PA12 Alternate Function mapping
* GPIO_Remap_ADC1_ETRGINJ - ADC1 External Trigger Injected Conversion remapping
* GPIO_Remap_ADC1_ETRGREG - ADC1 External Trigger Regular Conversion remapping
* GPIO_Remap_LSI_CAL - LSI calibration Alternate Function mapping
* GPIO_Remap_SDI_Disable - SDI Disabled
* NewState - ENABLE or DISABLE.
*
* @return none
*/
void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState)
{
uint32_t tmp = 0x00, tmp1 = 0x00, tmpreg = 0x00, tmpmask = 0x00;
tmpreg = AFIO->PCFR1;
tmpmask = (GPIO_Remap & DBGAFR_POSITION_MASK) >> 0x10;
tmp = GPIO_Remap & LSB_MASK;
if((GPIO_Remap & 0x10000000) == 0x10000000)
{
tmpreg &= ~((1<<1) | (1<<22));
tmpreg |= ~DBGAFR_SDI_MASK;
if(NewState != DISABLE)
{
tmpreg |= (GPIO_Remap & 0xEFFFFFFF);
}
}
else if((GPIO_Remap & 0x80000000) == 0x80000000)
{
tmpreg &= ~((1<<2) | (1<<21));
tmpreg |= ~DBGAFR_SDI_MASK;
if(NewState != DISABLE)
{
tmpreg |= (GPIO_Remap & 0x7FFFFFFF);
}
}
else if((GPIO_Remap & (DBGAFR_LOCATION_MASK | DBGAFR_NUMBITS_MASK)) == (DBGAFR_LOCATION_MASK | DBGAFR_NUMBITS_MASK))/* SDI */
{
tmpreg &= DBGAFR_SDI_MASK;
AFIO->PCFR1 &= DBGAFR_SDI_MASK;
if(NewState != DISABLE)
{
tmpreg |= (tmp << ((GPIO_Remap >> 0x15) * 0x10));
}
}
else if((GPIO_Remap & DBGAFR_NUMBITS_MASK) == DBGAFR_NUMBITS_MASK)/* [15:0] 2bit */
{
tmp1 = ((uint32_t)0x03) << tmpmask;
tmpreg &= ~tmp1;
tmpreg |= ~DBGAFR_SDI_MASK;
if(NewState != DISABLE)
{
tmpreg |= (tmp << ((GPIO_Remap >> 0x15) * 0x10));
}
}
else/* [31:0] 1bit */
{
tmpreg &= ~(tmp << ((GPIO_Remap >> 0x15) * 0x10));
tmpreg |= ~DBGAFR_SDI_MASK;
if(NewState != DISABLE)
{
tmpreg |= (tmp << ((GPIO_Remap >> 0x15) * 0x10));
}
}
AFIO->PCFR1 = tmpreg;
}
สามารถแก้ code เดิมได้ดังนี้
/*********************************************************************
* @brief Initializes the USARTx peripheral.
* @param baudrate - USART communication baud rate.
void USART_Printf_Init(uint32_t baudrate)
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_USART1 | RCC_APB2Periph_AFIO, ENABLE); // เปิด clock ให้กับ AFIO หากไม่เปิดจะไม่ทำงาน
GPIO_PinRemapConfig(GPIO_PartialRemap2_USART1, ENABLE); // กำหนดค่า REMAP TX:PD6, RX:PD5
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; // กำหนดขา GPIO
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOD, &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = baudrate;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Tx;
USART_Init(USART1, &USART_InitStructure);
USART_Cmd(USART1, ENABLE);
/*********************************************************************
* @fn USART_Printf_Init
*
* @brief Initializes the USARTx peripheral.
*
* @param baudrate - USART communication baud rate.
*
* @return None
*/
void USART_Printf_Init(uint32_t baudrate)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_USART1 | RCC_APB2Periph_AFIO, ENABLE); // เปิด clock ให้กับ AFIO หากไม่เปิดจะไม่ทำงาน
GPIO_PinRemapConfig(GPIO_PartialRemap2_USART1, ENABLE); // กำหนดค่า REMAP TX:PD6, RX:PD5
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; // กำหนดขา GPIO
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOD, &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = baudrate;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Tx;
USART_Init(USART1, &USART_InitStructure);
USART_Cmd(USART1, ENABLE);
}
/*********************************************************************
* @fn USART_Printf_Init
*
* @brief Initializes the USARTx peripheral.
*
* @param baudrate - USART communication baud rate.
*
* @return None
*/
void USART_Printf_Init(uint32_t baudrate)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_USART1 | RCC_APB2Periph_AFIO, ENABLE); // เปิด clock ให้กับ AFIO หากไม่เปิดจะไม่ทำงาน
GPIO_PinRemapConfig(GPIO_PartialRemap2_USART1, ENABLE); // กำหนดค่า REMAP TX:PD6, RX:PD5
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; // กำหนดขา GPIO
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOD, &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = baudrate;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Tx;
USART_Init(USART1, &USART_InitStructure);
USART_Cmd(USART1, ENABLE);
}
ตัว Framework ที่ทาง WCH ให้มาเป็นค่าตั้งต้น จะว่าเขียน code ไม่ง่าย ไม่ยาก ถ้ามาจากสายของ Arduino จำเป็นต้องล้างความคิดเดิมใหม่ทั้งหมด หากมาทางสาย STM32 จะสะดวกมากกว่า
การเขียนแนวนี้มันทำให้เราลงลึกไปถึงระดับ bit และ register กันเลยที่เดียว แต่นี้ก็ถือว่าเป็นโอกาศดีที่เราสามารถเรียนรู้ได้อย่างลึกซึ้ง สามารถนำไปต่อยอดกับ MCU ค่ายอื่นๆ ที่ไม่ได้รองรับ Arduino