[STM32#31] F103C8T6 blue pill board(블루필보드)를 cubeIDE와 ST-LINK를 이용해서 업로드하는 방법 알아보기!(녹칸다 내맘대로 STM32)
프로그래밍/STM32 2026. 2. 2. 23:00
https://youtube.com/live/SpbPhleFvAc
[STM32#31] F103C8T6 blue pill board(블루필보드)를 cubeIDE와 ST-LINK를 이용해서 업로드하는 방법 알아보기!(녹칸다 내맘대로 STM32)
심심한녹칸다의 내맘대로 STM32시리즈이다!
STM32시리즈의 모든 자료는 구글 슬라이드에 작성하고 모두에게 공유되어있음!
https://docs.google.com/presentation/d/1myA5iYbjuKsLWLqtRLKAiRfwUwvqB1d1RGjiMIIgp3I/edit?slide=id.g3bc8a5e1652_2_99#slide=id.g3bc8a5e1652_2_99
이번편은 뉴클레오 보드가 아니라 블루필 보드를 알아보도록 하겠습니다!
1.블루필보드에 내장되어있는 PC13번핀을 1초 간격으로 토글하시오!

while (1)
{
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
HAL_Delay(1000);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
2.블루필보드가 1초간격으로 “NOCKANDA!!\n”라는 문자열을 USB CDC를 이용해서 시리얼 출력한뒤 PC에서 putty로 확인하시오!

/* USER CODE BEGIN 2 */
char msg[] = "NOCKANDA!!\n";
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
CDC_Transmit_FS(msg, strlen(msg));
HAL_Delay(1000);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
3.PB8, PB9핀에 LED를 1개씩 연결하고 1초 간격으로 서로 번갈아가면서 LED가 점멸되도록 하시오!

while (1)
{
//PB8 ON PB9 OFF
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, 1);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9, 0);
HAL_Delay(1000);
//PB8 OFF PB9 ON
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, 0);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9, 1);
HAL_Delay(1000);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
4.PB6,PB7에 버튼(택트스위치)을 1개씩 연결하고 버튼을 누르면 PB6은 PB8 LED가 토글되고, PB7은 PB9 LED가 토글되도록 하시오!(버튼의 연결은 풀업방식)

while (1)
{
//PB6을 누르면 PB8이 토글된다
if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_6) == 0){
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_8);
HAL_Delay(200); //너무 빠르게 눌려지는 것 방지!
}
//PB7을 누르면 PB9가 토글된다
if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7) == 0){
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_9);
HAL_Delay(200); //너무 빠르게 눌려지는 것 방지!
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
5.PB6 버튼을 누르면 PC시리얼화면에 “NOCKANDA!!\n”라고 출력되고 PB7을 누르면 “SUBSCRIBE!!\n”라고 출력되도록 하시오!

/* USER CODE BEGIN 2 */
uint8_t msg1[] = "NOCKANDA!!\n";
uint8_t msg2[] = "SUBSCRIBE!!\n";
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
//PB6을 누르면 PB8이 토글된다
if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_6) == 0){
CDC_Transmit_FS(msg1, strlen(msg1));
HAL_Delay(200); //너무 빠르게 눌려지는 것 방지!
}
//PB7을 누르면 PB9가 토글된다
if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7) == 0){
CDC_Transmit_FS(msg2, strlen(msg2));
HAL_Delay(200); //너무 빠르게 눌려지는 것 방지!
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
6.PA0에 가변저항을 연결해서 가변저항값을 PC의 시리얼 화면에 100밀리초 간격으로 출력하시오!

/* USER CODE BEGIN 2 */
HAL_ADC_Start(&hadc1); //딱 한번만 호출
uint16_t adc_value0 = 0;
char buff[50];
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
//측정할때마다 호출
if(HAL_ADC_PollForConversion(&hadc1, 10) == HAL_OK)
{
// 값 처리
adc_value0 = HAL_ADC_GetValue(&hadc1); //0~4095
sprintf(buff,"A0 = %d\n",adc_value0);
CDC_Transmit_FS(buff, strlen(buff));
}
HAL_Delay(100);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
7.PA0에 연결된 가변저항을 돌리면 서보모터(PB5)의 각도가 0~180도 사이로 바뀌도록 하시오!

/* USER CODE BEGIN 0 */
void set_servo(uint8_t degree){
//degree는 0~180도 범위이고 CCR4는 600부터 2400의 범위이다!
TIM3->CCR2 = (uint32_t)(600+(2400-600)*degree/180.0);
}
//0~4095범위의 값을 0~180사이로 변환!
uint16_t map(uint16_t analog){
return 180*analog/4095.0;
}
/* USER CODE END 0 */
/* USER CODE BEGIN 2 */
HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_2); //PB5
HAL_ADC_Start(&hadc1); //딱 한번만 호출
uint16_t adc_value0 = 0;
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
if(HAL_ADC_PollForConversion(&hadc1, 10) == HAL_OK)
{
// 값 처리
adc_value0 = HAL_ADC_GetValue(&hadc1); //0~4095
//0~4095를 0~180도 범위로 조정해야한다!
set_servo(map(adc_value0));
}
HAL_Delay(10);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
8.I2C통신으로 작동되는 1602LCD를 블루필보드에 연결해서 첫번째 줄에는 타이머카운터값을 출력하고 두번째 줄에는 PA0에 연결된 가변저항값을 출력하시오!

#define delay_ms HAL_Delay
#define SYS_CLOCK 72
#define SYSTICK_LOAD 72000-1
uint32_t millis_cnt = 0;
uint32_t millis() {
return millis_cnt;
}
uint32_t micros() {
return (millis_cnt & 0x3FFFFF) * 1000 + (SYSTICK_LOAD - SysTick->VAL) / SYS_CLOCK;
}
void delay_us(uint32_t us) { // 64MHz 보정
if (us > 1) {
uint32_t count = us * 7 - 6;
while (count--);
} else {
uint32_t count = 2;
while (count--);
}
}
#define ADDRESS 0x27<<1
#define RS1_EN1 0x05
#define RS1_EN0 0x01
#define RS0_EN1 0x04
#define RS0_EN0 0x00
#define BackLight 0x08
// RS-Q0 / RW-Q1 / EN-Q2 / BackLight-Q3 / D4-Q4 / D5-Q5 / D6-Q6 / D7-Q7
void LCD_DATA(uint8_t data) {
uint8_t temp=(data & 0xF0)|RS1_EN1|BackLight;
while(HAL_I2C_Master_Transmit(&hi2c1, ADDRESS, &temp, 1, 1000)!=HAL_OK);
temp=(data & 0xF0)|RS1_EN0|BackLight;
while(HAL_I2C_Master_Transmit(&hi2c1, ADDRESS, &temp, 1, 1000)!=HAL_OK);
delay_us(4);
temp=((data << 4) & 0xF0)|RS1_EN1|BackLight;
while(HAL_I2C_Master_Transmit(&hi2c1, ADDRESS, &temp, 1, 1000)!=HAL_OK);
temp = ((data << 4) & 0xF0)|RS1_EN0|BackLight;
while(HAL_I2C_Master_Transmit(&hi2c1, ADDRESS, &temp, 1, 1000)!=HAL_OK);
delay_us(50);
}
void LCD_CMD(uint8_t cmd) {
uint8_t temp=(cmd & 0xF0)|RS0_EN1|BackLight;
while(HAL_I2C_Master_Transmit(&hi2c1, ADDRESS, &temp, 1, 1000)!=HAL_OK);
temp=(cmd & 0xF0)|RS0_EN0|BackLight;
while(HAL_I2C_Master_Transmit(&hi2c1, ADDRESS, &temp, 1, 1000)!=HAL_OK);
delay_us(4);
temp=((cmd << 4) & 0xF0)|RS0_EN1|BackLight;
while(HAL_I2C_Master_Transmit(&hi2c1, ADDRESS, &temp, 1, 1000)!=HAL_OK);
temp=((cmd << 4) & 0xF0)|RS0_EN0|BackLight;
while(HAL_I2C_Master_Transmit(&hi2c1, ADDRESS, &temp, 1, 1000)!=HAL_OK);
delay_us(50);
}
void LCD_CMD_4bit(uint8_t cmd) {
uint8_t temp=((cmd << 4) & 0xF0)|RS0_EN1|BackLight;
while(HAL_I2C_Master_Transmit(&hi2c1, ADDRESS, &temp, 1, 1000)!=HAL_OK);
temp=((cmd << 4) & 0xF0)|RS0_EN0|BackLight;
while(HAL_I2C_Master_Transmit(&hi2c1, ADDRESS, &temp, 1, 1000)!=HAL_OK);
delay_us(50);
}
void LCD_INIT(void) {
delay_ms(100);
LCD_CMD_4bit(0x03); delay_ms(5);
LCD_CMD_4bit(0x03); delay_us(100);
LCD_CMD_4bit(0x03); delay_us(100);
LCD_CMD_4bit(0x02); delay_us(100);
LCD_CMD(0x28); // 4 bits, 2 line, 5x8 font
LCD_CMD(0x08); // display off, cursor off, blink off
LCD_CMD(0x01); // clear display
delay_ms(3);
LCD_CMD(0x06); // cursor movint direction
LCD_CMD(0x0C); // display on, cursor off, blink off
}
void LCD_XY(char x, char y) {
if (y == 0) LCD_CMD(0x80 + x);
else if (y == 1) LCD_CMD(0xC0 + x);
else if (y == 2) LCD_CMD(0x94 + x);
else if (y == 3) LCD_CMD(0xD4 + x);
}
void LCD_CLEAR(void) {
LCD_CMD(0x01);
delay_ms(2);
}
void LCD_PUTS(char *str) {
while (*str) LCD_DATA(*str++);
}
/* USER CODE BEGIN 2 */
LCD_INIT(); //1회호출(메인루프 시작전)
HAL_ADC_Start(&hadc1); //딱 한번만 호출
uint16_t adc_value0 = 0;
uint8_t line1[20];
uint8_t line2[20];
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
if(HAL_ADC_PollForConversion(&hadc1, 10) == HAL_OK)
{
// 값 처리
adc_value0 = HAL_ADC_GetValue(&hadc1);
sprintf(line1,"CNT = %10d",HAL_GetTick());
sprintf(line2,"PA0 = %10d",adc_value0);
LCD_XY(0, 0) ; LCD_PUTS(line1);
LCD_XY(0, 1) ; LCD_PUTS(line2);
}
HAL_Delay(100);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}

