در قسمت اول معرفی CH32X035C8T6؛ معماری RISC-V، حافظه و کلاک، به معرفی کلی این چیپ RISC-V محبوب شرکت WCH، مشخصات فنی، سیستم کلاک، بخش منحصربهفرد PIOC و پروتکل پرکاربرد USB-PD پرداختیم. اگر هنوز بخش نخست را مطالعه نکردهاید، پیشنهاد میکنیم حتماً ابتدا نگاهی به قسمت اول بیندازید تا با معماری کلی این تراشه صنعتی آشنا شوید.
حال در قسمت دوم این راهنما، وارد لایههای عملیاتیتر و پریفرالهای داخلی میشویم؛ از نحوه راهاندازی ADC ۱۲ بیتی و قابلیت خازنی TouchKey گرفته تا خروجیهای PWM، وقفههای خارجی و پروتکلهای ارتباطی پرکاربرد نظیر UART، SPI، I2C و واحد DMA با ارائهی نمونهکدهای کاربردی در محیط MounRiver Studio.
مبدل آنالوگ-دیجیتال ۱۲ بیتی در پکیج C8T6 به ۱۰ کانال خارجی (A0 تا + A9) یک کانال داخلی (ولتاژ مرجع داخلی ~۱٫۲V برای سنجش تغذیه) دسترسی دارد. مشخصات کلیدی از دیتاشیت:

قالب پایه خواندن ADC با کتابخانه استاندارد، سه مرحله دارد: پیکربندی پایه به صورت ورودی آنالوگ، تنظیم ساختار ADC_InitTypeDef با کلاک ۸MHz، و سپس تریگر نرمافزاری با انتظار فلگ EOC:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | /* CH32X035 - ADC single conversion on A1 (PA1) * MounRiver Studio II - WCH standard peripheral library */ #include "debug.h" void ADC_Function_Init( void ) { ADC_InitTypeDef ADC_InitStructure = {0}; GPIO_InitTypeDef GPIO_InitStructure = {0}; RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE ); RCC_APB2PeriphClockCmd( RCC_APB2Periph_ADC1, ENABLE ); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; /* A1 = PA1 */ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; /* analog in */ GPIO_Init( GPIOA, &GPIO_InitStructure ); ADC_DeInit( ADC1 ); ADC_CLKConfig( ADC1, ADC_CLK_Div6 ); /* 48/6 = 8MHz */ ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; ADC_InitStructure.ADC_ScanConvMode = DISABLE; ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfChannel = 1; ADC_Init( ADC1, &ADC_InitStructure ); ADC_Cmd( ADC1, ENABLE ); } u16 Get_ADC_Val( u8 ch ) { u16 val; ADC_RegularChannelConfig( ADC1, ch, 1, ADC_SampleTime_11Cycles ); ADC_SoftwareStartConvCmd( ADC1, ENABLE ); /* SW trigger */ while( !ADC_GetFlagStatus( ADC1, ADC_FLAG_EOC ) ); val = ADC_GetConversionValue( ADC1 ); return val; } int main( void ) { SystemCoreClockUpdate(); Delay_Init(); USART_Printf_Init( 115200 ); ADC_Function_Init( ); printf( "ADC(A1) = %d\r\n", Get_ADC_Val( ADC_Channel_1 ) ); while( 1 ); } |
TouchKey: واحد تشخیص خازنی با ۱۰ کانال روی همان پایه های ADC کار میکند و کتابخانه الگوریتم تشخیص لمس در EVT ارائه شده — مناسب کلیدهای لمسی پنل های صنعتی با روکش شیشه ای. واحد TouchKey روی زیرساخت ADC سوار است: زمان شارژ/تخلیه در رجیسترهای اختصاصی TKey تنظیم میشود و کاهش شمارنده پس از لمس، معیار تشخیص است؛ الگوریتم مرجع فیلترکردن و آستانه گذاری در همان مثال EVT آمده است:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | /* CH32X035 - TouchKey detection on channel 2 (PA2) * MounRiver Studio II - based on EVT example "TKey" */ #include "debug.h" void Touch_Key_Init( void ) { GPIO_InitTypeDef GPIO_InitStructure = {0}; ADC_InitTypeDef ADC_InitStructure = {0}; RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE ); RCC_APB2PeriphClockCmd( RCC_APB2Periph_ADC1, ENABLE ); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; /* TK2 = PA2 */ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; GPIO_Init( GPIOA, &GPIO_InitStructure ); ADC_CLKConfig( ADC1, ADC_CLK_Div6 ); ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; ADC_InitStructure.ADC_ScanConvMode = DISABLE; ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfChannel = 1; ADC_Init( ADC1, &ADC_InitStructure ); ADC_Cmd( ADC1, ENABLE ); TKey1->CTLR1 |= ( 1 << 24 ); /* TouchKey enable */ } u16 Touch_Key_Adc( u8 ch ) { ADC_RegularChannelConfig( ADC1, ch, 1, ADC_SampleTime_11Cycles ); TKey1->IDATAR1 = 0x80; /* charge time */ TKey1->RDATAR = 0x8; /* discharge time */ while( !ADC_GetFlagStatus( ADC1, ADC_FLAG_EOC ) ); return ( u16 ) TKey1->RDATAR; } int main( void ) { u16 TK_val; SystemCoreClockUpdate(); Delay_Init(); USART_Printf_Init( 115200 ); Touch_Key_Init( ); while( 1 ) { TK_val = Touch_Key_Adc( ADC_Channel_2 ); printf( "TouchKey Value:%d\r\n", TK_val ); /* lower = touched */ Delay_Ms( 200 ); } } |
محدودیت بچ های تولید طبق دیتاشیت، در بچ هایی که رقم پنجم از آخر شماره بچ «0» است، توابع I2C و کانال های ADC شماره ۱۱ ۷، ۳، و ۱۵ موجود نیستند. برای تولید انبوه، این نکته را هنگام خرید و تست ورودی قطعات لحاظ کنید.

خروجی PWM با تایمرهای پیشرفته TIM1/TIM2 پیاده میشود؛ نکته اختصاصی WCH آن است که برای رسیدن خروجی پایه به دست میآید. مثال زیر ۱ کیلوهرتز با دورۀ ۵۰٪ روی PB9 تولید میکند:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | /* CH32X035 - TIM1_CH1 (PB9) PWM output: 1kHz @ 50% duty * MounRiver Studio II - based on EVT example "PWM_Output" */ #include "debug.h" void TIM1_PWMOut_Init( u16 arr, u16 psc, u16 ccp ) { GPIO_InitTypeDef GPIO_InitStructure = {0}; TIM_OCInitTypeDef TIM_OCInitStructure = {0}; TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure = {0}; RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB | RCC_APB2Periph_TIM1, ENABLE ); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; /* TIM1_CH1 = PB9 */ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init( GPIOB, &GPIO_InitStructure ); TIM_TimeBaseInitStructure.TIM_Period = arr; /* period */ TIM_TimeBaseInitStructure.TIM_Prescaler = psc; /* clock divider */ TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit( TIM1, &TIM_TimeBaseInitStructure ); TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = ccp; /* duty = ccp/arr */ TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OC1Init( TIM1, &TIM_OCInitStructure ); TIM_CtrlPWMOutputs( TIM1, ENABLE ); /* MOE bit */ TIM_OC1PreloadConfig( TIM1, TIM_OCPreload_Disable ); TIM_ARRPreloadConfig( TIM1, ENABLE ); TIM_Cmd( TIM1, ENABLE ); } int main( void ) { SystemCoreClockUpdate(); Delay_Init(); USART_Printf_Init( 115200 ); /* 48MHz / 48000 / 100 = 1kHz , pulse 50 -> 50% duty */ TIM1_PWMOut_Init( 100, 48000-1, 50 ); while( 1 ); } |
۴ × USART با،LIN،،ISO7816 IrDA کنترل جریان سخت افزاری CTS/RTS، بادریت کسری و DMA — پیش فرض: USART1 روی،PB10/PB11 USART2 روی،PA2/PA3 USART3 روی،PB3/PB4 USART4 روی PB0/PB1؛ SPI مستر/اسلیو (پیش فرض PA4..PA7) با داده ۸/۱۶ بیتی، CRC سخت افزاری و پشتیبانی SD/MMC؛ I2C با آدرس دهی ۷/۱۰ بیتی، دو آدرس اسلیو و سرعت Standard/Fast (پیش فرض PA10/PA11)؛ DMA با ۸ کانال عمومی + کانال اختصاصی برای USBFS و + USBPD پشتیبانی TIM/ADC/USART/I2C/SPI؛:GPIO ۴۶ پایه با Pull-up داخلی همگانی، Pull-down فقط روی PA15–PA0 و PC16/17، درایو جریان بالاتر در پورت های A و B، مکانیزم قفل پیکربندی IO، و ۲۴ خط وقفه خارجی.
وقفه خارجی: ۲۴ خط EXTI در دو گروه وقفه EXTI7_0 و EXTI15_8 جمع میشوند؛ برای ورودی های میدانی صنعتی، فیلتر RC خارجی + لبه نزولی همان الگوی استاندارد است:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | /* CH32X035 - external interrupt on PA0 (falling edge) * MounRiver Studio II - based on EVT example "EXTI0" */ #include "debug.h" void EXTI0_INT_INIT( void ) { GPIO_InitTypeDef GPIO_InitStructure = {0}; EXTI_InitTypeDef EXTI_InitStructure = {0}; NVIC_InitTypeDef NVIC_InitStructure = {0}; RCC_APB2PeriphClockCmd( RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA, ENABLE ); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; /* pull-up input */ GPIO_Init( GPIOA, &GPIO_InitStructure ); /* GPIOA.0 ----> EXTI_Line0 */ GPIO_EXTILineConfig( GPIO_PortSourceGPIOA, GPIO_PinSource0 ); EXTI_InitStructure.EXTI_Line = EXTI_Line0; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init( &EXTI_InitStructure ); NVIC_InitStructure.NVIC_IRQChannel = EXTI7_0_IRQn; /* EXTI lines 0..7 */ NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init( &NVIC_InitStructure ); } void EXTI7_0_IRQHandler( void ) __attribute__( ( interrupt( "WCH-Interrupt-fast" ) ) ); void EXTI7_0_IRQHandler( void ) { if( EXTI_GetITStatus( EXTI_Line0 ) != RESET ) { /* field input arrived - latch it, then clear the flag */ EXTI_ClearITPendingBit( EXTI_Line0 ); } } int main( void ) { NVIC_PriorityGroupConfig( NVIC_PriorityGroup_1 ); SystemCoreClockUpdate(); Delay_Init(); USART_Printf_Init( 115200 ); EXTI0_INT_INIT( ); while( 1 ) { Delay_Ms( 1000 ); /* main loop ... */ } } |
ADC با DMA: برای پایش پیوسته سنسورهای آنالوگ بدون بار CPU، نتایج ADC به صورت خودکار با DMA به حافظه منتقل میشود:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | /* CH32X035 - ADC channel A1 (PA1): 1024 samples moved by DMA * MounRiver Studio II - based on EVT example "ADC_DMA" */ #include "debug.h" #define N 1024 u16 TxBuf[ N ]; void ADC_Function_Init( void ) { ADC_InitTypeDef ADC_InitStructure = {0}; GPIO_InitTypeDef GPIO_InitStructure = {0}; RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE ); RCC_APB2PeriphClockCmd( RCC_APB2Periph_ADC1, ENABLE ); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; /* A1 = PA1 */ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; GPIO_Init( GPIOA, &GPIO_InitStructure ); ADC_DeInit( ADC1 ); ADC_CLKConfig( ADC1, ADC_CLK_Div6 ); /* 8MHz ADC clock */ ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; ADC_InitStructure.ADC_ScanConvMode = DISABLE; ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; /* continuous mode */ ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfChannel = 1; ADC_Init( ADC1, &ADC_InitStructure ); ADC_DMACmd( ADC1, ENABLE ); /* ADC -> DMA */ ADC_Cmd( ADC1, ENABLE ); } void DMA_Tx_Init( DMA_Channel_TypeDef *DMA_CHx, u32 ppadr, u32 memadr, u16 bufsize ) { DMA_InitTypeDef DMA_InitStructure = {0}; RCC_AHBPeriphClockCmd( RCC_AHBPeriph_DMA1, ENABLE ); DMA_DeInit( DMA_CHx ); DMA_InitStructure.DMA_PeripheralBaseAddr = ppadr; /* ADC data reg */ DMA_InitStructure.DMA_MemoryBaseAddr = memadr; /* TxBuf */ DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_BufferSize = bufsize; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init( DMA_CHx, &DMA_InitStructure ); } int main( void ) { u16 i; SystemCoreClockUpdate(); Delay_Init(); USART_Printf_Init( 115200 ); ADC_Function_Init( ); DMA_Tx_Init( DMA1_Channel1, ( u32 )&ADC1->RDATAR, ( u32 )TxBuf, N ); DMA_Cmd( DMA1_Channel1, ENABLE ); ADC_RegularChannelConfig( ADC1, ADC_Channel_1, 1, ADC_SampleTime_11Cycles ); ADC_SoftwareStartConvCmd( ADC1, ENABLE ); while( DMA_GetFlagStatus( DMA1_FLAG_TC1 ) == RESET ); /* wait 1024 samples */ ADC_SoftwareStartConvCmd( ADC1, DISABLE ); for( i = 0; i < N; i++ ) printf( "%04d\r\n", TxBuf[ i ] ); while( 1 ); } |
SPI: قالب مستر تمام دوطرفه روی پایه های پیش فرض PA4،(CS) PA5،(SCK) PA6 (MISO) و PA7: (MOSI)
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | /* CH32X035 - SPI1 master: full-duplex 16-bit transfer * MounRiver Studio II - based on EVT example "2Lines_FullDuplex" */ #include "debug.h" void SPI_FullDuplex_Init( void ) { GPIO_InitTypeDef GPIO_InitStructure = {0}; SPI_InitTypeDef SPI_InitStructure = {0}; RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | RCC_APB2Periph_SPI1, ENABLE ); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; /* SCK */ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init( GPIOA, &GPIO_InitStructure ); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; /* MISO */ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init( GPIOA, &GPIO_InitStructure ); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; /* MOSI */ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init( GPIOA, &GPIO_InitStructure ); SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_Mode = SPI_Mode_Master; SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b; SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64; SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_InitStructure.SPI_CRCPolynomial = 7; SPI_Init( SPI1, &SPI_InitStructure ); SPI_Cmd( SPI1, ENABLE ); } int main( void ) { u8 i = 0, j = 0; u16 TxData[ 4 ] = { 0x0101, 0x0202, 0x0303, 0x0404 }; u16 RxData[ 4 ]; SystemCoreClockUpdate(); Delay_Init(); USART_Printf_Init( 115200 ); SPI_FullDuplex_Init( ); while( ( i < 4 ) || ( j < 4 ) ) { if( ( i < 4 ) && ( SPI_I2S_GetFlagStatus( SPI1, SPI_I2S_FLAG_TXE ) != RESET ) ) { SPI_I2S_SendData( SPI1, TxData[ i++ ] ); /* TX empty */ } if( ( j < 4 ) && ( SPI_I2S_GetFlagStatus( SPI1, SPI_I2S_FLAG_RXNE ) != RESET ) ) { RxData[ j++ ] = SPI_I2S_ReceiveData( SPI1 ); /* RX full */ } } while( 1 ); } |
I2C: برای سنسورها و EEPROMهای صنعتی؛ دقت کنید I2C با خروجی Open-Drain کار میکند و مقاومت Pull-up خارجی (معمولا 4.7k) روی SCL/SDA لازم است:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | /* CH32X035 - I2C1 master @100kHz: write 6 bytes to slave 0x02 * MounRiver Studio II - based on EVT example "I2C_7bit_Mode" */ #include "debug.h" void IIC_Init( u32 bound, u16 address ) { GPIO_InitTypeDef GPIO_InitStructure = {0}; I2C_InitTypeDef I2C_InitTSturcture = {0}; RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE ); RCC_APB1PeriphClockCmd( RCC_APB1Periph_I2C1, ENABLE ); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; /* SCL */ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init( GPIOA, &GPIO_InitStructure ); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; /* SDA */ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init( GPIOA, &GPIO_InitStructure ); I2C_InitTSturcture.I2C_ClockSpeed = bound; I2C_InitTSturcture.I2C_Mode = I2C_Mode_I2C; I2C_InitTSturcture.I2C_DutyCycle = I2C_DutyCycle_16_9; I2C_InitTSturcture.I2C_OwnAddress1 = address; I2C_InitTSturcture.I2C_Ack = I2C_Ack_Enable; I2C_InitTSturcture.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; I2C_Init( I2C1, &I2C_InitTSturcture ); I2C_Cmd( I2C1, ENABLE ); I2C_AcknowledgeConfig( I2C1, ENABLE ); } int main( void ) { u8 i; u8 TxData[ 6 ] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 }; SystemCoreClockUpdate(); Delay_Init(); USART_Printf_Init( 115200 ); IIC_Init( 100000, 0x02 ); while( I2C_GetFlagStatus( I2C1, I2C_FLAG_BUSY ) != RESET ); I2C_GenerateSTART( I2C1, ENABLE ); /* START */ while( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_MODE_SELECT ) ); I2C_Send7bitAddress( I2C1, 0x02, I2C_Direction_Transmitter ); while( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED ) ); for( i = 0; i < 6; i++ ) /* data */ { I2C_SendData( I2C1, TxData[ i ] ); while( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED ) ); } I2C_GenerateSTOP( I2C1, ENABLE ); /* STOP */ while( 1 ); } |
سخن پایانی و ادامه مسیر
در این قسمت توانستیم پریفرالهای حیاتی CH32X035C8T6 از قبیل مبدل آنالوگ، کلیدهای لمسی، تایمرهای PWM و رابطهای سریال را به کمک کتابخانه استاندارد WCH راهاندازی و کنترل کنیم. تسلط بر پیکربندی این واحدها و هماهنگی آنها با DMA، بار پردازشی هسته را به حداقل رسانده و بستری کاملاً پایدار برای کاربردهای حساس صنعتی فراهم میسازد. پرونده این ماژول میکروکنترلر اختصاصی جذاب هنوز بسته نشده است؛ در قسمت بعدی این مجموعه مقالات، به سراغ مباحث تکمیلی خواهیم رفت. نظرات و چالشهای خود را در راهاندازی این بخشها با ما در میان بگذارید.
سیسوگ با افتخار فضایی برای اشتراک گذاری دانش شماست. برای ما مقاله بنویسید.