CH32V103C8T6是沁恆的RISC-V內核MCU, 基於RISC-V3A處理器, 內核採用2級流水線處理,設置了靜態分支預測、指令預取機制,支持DMA. 需要準備一片 WCH-Link 用於燒錄沁恆的晶元. 市面上有相容 DAP-Link 和 WCH-Link 的燒錄器. 註意看燒錄器的說明,... ...
CH32V103C8T6
CH32V103C8T6是沁恆的RISC-V內核MCU, 基於RISC-V3A處理器, 內核採用2級流水線處理,設置了靜態分支預測、指令預取機制,支持DMA. 主要參數如下
- CPU: 32位RISC-V3A, RV32IMAC指令集, 最高80MHz, 典型72MHz
- RAM: 20KB
- Flash: 64KB
- BootLoader: 3.75KB 系統引導程式存儲區
- 供電: 2.7V - 5.5V (相容3.3V和5V)
- Timer: 通用3, 高級1, 看門狗2, 系統時鐘1
- ADC: 12bit, 10CH
- SPI: 2
- I2C: 2
- UART: 3
- USBHD: 1
- 封裝: LQFP48
硬體部分
燒錄器 WCH-Link
需要準備一片 WCH-Link 用於燒錄沁恆的晶元. 市面上有相容 DAP-Link 和 WCH-Link 的燒錄器. 註意看燒錄器的說明, 其模式在加電前通過按鍵可以切換. 燒錄 CH32V103 時, 必須處於 WCH-Link的狀態
開發板 Blue Pill
因為 CH32V103C8T6 引腳佈局與 STM32F103C8T6, CH32F103C8T6 完全一致, 硬體設計通用,PIN對PIN相容, 所以可以直接使用 STM32F103C8T6 核心板(Blue Pill)作為開發板.
手裡正好有一片 STM32F103C6T6 的開發板, 電路和 STM32F103C8T6 是一樣的, 只是晶元型號不同, 於是用熱風焊將C6T6吹下來, 把 CH32V103C8T6 換上去.
熱風槍溫度設置成290度, MCU加上助焊油, STM32F103C6T6 吹掉之後的焊盤
焊上了 CH32V103C8T6, 第一次放得有點歪
又吹了一遍, 這次小心放正了
測了一遍各PIN腳間電阻, 感覺有些PIN虛焊了, 所以又用電烙鐵拖了一遍
連線
WCH-Link -> Blue Pill
3V3 -> 3V3
GND -> GND
SWD -> SWIO
SCK -> SWCLK
RX -> PA9
TX -> PA10
如果不觀察串口輸出的話, RX/TX可以不連
軟體部分
軟體部分其實就是 MounRiver Studio, 下載完解壓後安裝. MounRiver Studio 是基於 Eclipse 的擴展開發環境, 對於熟悉 Eclipse 的人用起來還比較方便. 安裝 MounRiver Studio 的同時, WCH-Link 的驅動就裝上了, 不需要再另外安裝.
- 下載地址 http://mounriver.com/download
- 使用介紹
如果需要觀察串口輸出, 還需要使用串口工具, 例如 putty.
測試項目
創建項目
下麵建一個測試項目, 通過GPIO驅動板子上的PC13 LED
File -> New -> MounRiver Project, 在對話框中
- 選擇晶元型號 WCH -> CH32V103 [RIsC-V] -> CH32V103C8T6
- 輸入Project Name, 例如 Test001
- 勾選 Use default location, 如果需要放到其他目錄, 這裡可以不勾選, 自行選擇
- Template Type 選擇 NoneOS, 因為這隻是個簡單測試, 只需要while迴圈即可
- 點擊 Finish
在項目 Project Explorer 中會出現目錄結構,
編輯代碼
用戶代碼在 User 目錄下, 展開 User, 打開 main.c 將內容修改為
#include "debug.h"
void GPIO_Toggle_INIT(void)
{
GPIO_InitTypeDef GPIO_InitStructure = {0};
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
}
int main(void)
{
u8 i = 0;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
Delay_Init();
USART_Printf_Init(115200);
printf("SystemClk:%d\r\n", SystemCoreClock);
printf("GPIO Toggle TEST\r\n");
GPIO_Toggle_INIT();
while(1)
{
Delay_Ms(500);
GPIO_WriteBit(GPIOC, GPIO_Pin_13, (i == 0) ? (i = Bit_SET) : (i = Bit_RESET));
printf("TEST\r\n");
}
}
編譯項目
編譯和燒錄的過程, MounRiver 都已經包裝得很好, 所以這部分比較簡單.
使用圖標欄中的編譯按鈕, 或者按F7
編譯項目(完整編譯使用Shift
+F7
)
燒錄
首先在設備管理器中查看 Ports (COM & LPT), 如果燒錄器處於WCH-Link狀態並且已經連接電腦, 會出現 WCH-LinkRV SERIAL(COMx) 這樣的設備
使用圖標欄中的下載按鈕(Download), 或者按F8
燒錄.
如果以上步驟都正常, 應該能看到開發板上的LED每隔半秒切換一次亮滅狀態. 串口使用115200波特率連接, 能看到輸出的文字"TEST"
其他測試
PWM輸出
#include "debug.h"
/* PWM Output Mode Definition */
#define PWM_MODE1 0
#define PWM_MODE2 1
/* PWM Output Mode Selection */
#define PWM_MODE PWM_MODE1
//#define PWM_MODE PWM_MODE2
void TIM1_PWMOut_Init(uint16_t arr, uint16_t psc, uint16_t ccp)
{
GPIO_InitTypeDef GPIO_InitStructure = {0};
TIM_OCInitTypeDef TIM_OCInitStructure = {0};
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure = {0};
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_TIM1, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
TIM_TimeBaseInitStructure.TIM_Period = arr;
TIM_TimeBaseInitStructure.TIM_Prescaler = psc;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseInitStructure);
#if(PWM_MODE == PWM_MODE1)
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
#elif(PWM_MODE == PWM_MODE2)
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
#endif
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = ccp;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
TIM_CtrlPWMOutputs(TIM1, ENABLE);
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Disable);
TIM_ARRPreloadConfig(TIM1, ENABLE);
TIM_Cmd(TIM1, ENABLE);
}
int main(void)
{
uint8_t i = 0, d = 0;
Delay_Init();
USART_Printf_Init(115200);
printf("SystemClk:%d\r\n", SystemCoreClock);
TIM1_PWMOut_Init(255, 72 - 1, i);
while(1)
{
Delay_Ms(10);
if (d == 0)
{
TIM_SetCompare1(TIM1, i++);
if (i == 255) d = 1;
}
else
{
TIM_SetCompare1(TIM1, i--);
if (i == 0) d = 0;
}
}
}
參考
- 硬體和接線 https://blog.51cto.com/u_15127636/4347970
- MounRiver Studio 燒錄
- https://github.com/weimingtom/wmt_ch32_study