sigma

Bluetooth remote control car based on Liangshanpai development board

 
Overview

The smart car can use ultrasonic distance measurement and display information on the OLED screen. If the distance of the object in front is less than 10cm, the buzzer will sound an alarm. The Bluetooth module can be used to control the car to move forward, backward, rotate left, and rotate right. The LED light in front of the car will light up according to the direction of rotation. The car can also detect the battery adc voltage and display it on the screen. Bluetooth control is to download the HC Bluetooth Assistant from the official website of HC on the mobile phone and then use the custom button to send data to the HC_05 Bluetooth module. The serial port of the development board is used to receive the sent data and then make corresponding actions (currently only basic operations can be completed and the code will be improved later).
There are some errors in the first design. The errors have been modified now. The modifications are as follows: 1. The ground connection of the buzzer is wrong. After modification, the original board is processed with flying wires and it has been verified to be normal. 2. The original board used PA10 to control the motor chip. Because PA10 is a download pin, the motor will rotate as soon as it is powered on, and sometimes the program cannot be downloaded. Then change PA10 to PB6.

# 1. Project Introduction
Bluetooth Remote Control Car Based on Liangshan Development Board
# 2. Function Introduction
Function:
1. Use Bluetooth to control the car, using the hc_05 module, and download the official control software of hc on the mobile phone.
2. The OLED screen displays the distance of the object in front of the car, the forward speed gear, and the adc of the battery voltage.
3. Ultrasonic obstacle avoidance.
4. Buzzer alarm.
5. The lights show different states when turning left and right, and the LED on the development board will display the running lights according to the direction.
6. The button controls the gear when the car moves forward.
# Circuit Analysis
## 1. Power module
! [QQ screenshot 20221220103913.png] Two 18650 batteries are connected in series, first through a voltage regulator diode for voltage stabilization, then through a switch, it can be output as the voltage for driving the motor, and then through the step-down chip to output a 5V voltage, in which two tantalum capacitors are connected in parallel for filtering.
## 2. Buzzer module
! [QQ screenshot 20221220105047.png] When the BUZZER pin outputs a high level, the buzzer is turned on. The pin selects PB4, which can be configured as a timer output. The code has been configured as a timer output, and the frequency of the sound emitted can be controlled by changing the input value.
```
#include "bsp_buzzer.h"
void buzzer_config(void)
{
/* Enable clock*/
rcu_periph_clock_enable(RCU_BUZZER);
/* Configure as output mode multiplexing mode*/
gpio_mode_set(PORT_BUZZER,GPIO_MODE_AF,GPIO_PUPD_NONE,PIN_BUZZER);
/* Configure as push-pull output 50MHZ */
gpio_output_options_set(PORT_BUZZER,GPIO_OTYPE_PP,GPIO_OSPEED_50MHZ,PIN_BUZZER);
gpio_af_set(PORT_BUZZER,GPIO_AF_2,PIN_BUZZER);//Configure GPIO multiplexing
}
void buzzer_on(uint16_t speed)
{
gpio_mode_set(PORT_BUZZER,GPIO_MODE_AF,GPIO_PUPD_NONE,PIN_BUZZER); //Multiplexed push-pull output
timer_channel_output_pulse_value_config(BSP_PWM2_TIMER,BSP_PWM0_CHANNEL_0,speed); // Configure the timer channel output pulse value

}
```
## 3. Key circuit
![QQ screenshot 20221220105838.png] Set the key pin to pull-up mode. If the button is pressed, the pin level will be pulled low. The code initializes the key pin on the development board together, and can display the speed gear on the OLED screen.
```
#include "bsp_key.h"
#include "sys.h"
#include "bsp_led.h "
#include "stdio.h"

void key_gpio_config(void)
{
/*Turn on the GPIO clock*/
rcu_periph_clock_enable(BSP_KEY_RCU);
rcu_periph_clock_enable(RCU_SYSCFG);
rcu_periph_clock_enable(BSP_KEY1_R CU);
/*Configure GPIO clock mode*/
gpio_mode_set(BSP_KEY_PORT, GPIO_MODE_INPUT, GPIO_PUPD_PULLDOWN, BSP_KEY_PIN);

gpio_mode_set(BSP_KEY1_PORT,GPIO_MODE_INPUT,GPIO_PUPD_PULLUP,BSP_KEY1_PIN); // The default state of the key is high level, configured as pull-up
nvic_irq_enable(BSP_KEY_EXTI_IRQN,3U, 3U);
syscfg_exti_line_config(BSP_KEY_EXTI_PORT_SOURCE,BSP_KEY_EXTI_PIN_SOURCE );

exti_init(BSP_KEY_EXTI_LINE, EXTI_INTERRUPT, EXTI_TRIG_BOTH);
exti_interrupt_enable(BSP_KEY_EXTI_LINE);
exti_interrupt_flag_get(BSP_KEY_EXTI_LINE);
}
void BSP_KEY_EXTI_IRQHANDLER(void) //Function does not need to be called, does not occupy CPU time
{
if(exti_interrupt_flag_get(BSP_KEY_EXTI_LINE)==SET)
{
if(gpio_input_bit_get(BSP_KEY_PORT, BSP_KEY_PIN)==SET)
{
printf("key press!
");
}
else
{
printf("key release!
");
}
exti_interrupt_flag_clear(BSP_KEY_EXTI_LINE);
}

}
void key_scan(void)
{
/*Get the corresponding status of the key pin*/
if(gpio_input_bit_get(BSP_KEY_PORT, BSP_KEY_PIN)==SET)
{
delay_1ms(20);
if(gpio_input_bit_get(BSP_KEY_PORT, BSP_KEY_PIN)==SET)
{
gpio_bit_toggle(PORT_LED0,PIN_LED0);
printf("key press!/r/n");
while(gpio_input_bit_get(BSP_KEY_PORT, BSP_KEY_PIN)==SET);
printf("key release!/r/n");
}
}
}

uint8_t gearshift=1;
uint8_t KEY_Read(void)
{

/* Read the level of the key pin first. If it is low, the key is pressed*/
if(gpio_input_bit_get(BSP_KEY1_PORT,BSP_KEY1_PIN) == RESET) // Button pressed
{
delay_1ms(20); // Delay debounceif
(gpio_input_bit_get(BSP_KEY1_PORT,BSP_KEY1_PIN) == RESET) // Detect if the key is pressed again
{
gearshift++;
if(gearshift>3)
{
gearshift=1;

}
}
}

return gearshift;
}
void gearshift_show(void)
{
uint16_t a;
a=KEY_Read();
OLED_ShowString(1,3,"speed:",2);
OLED_ShowNum(60,3,a,1,2);
}

```
```
#ifndef _BSP_KEY_H
#define _BSP_KEY_H

#include "gd32f4xx.h"
#include "systick.h"
#include "bsp_oled.h"

#define BSP_KEY_RCU RCU_GPIOA
#define BSP_KEY_PORT GPIOA
#define BSP_KEY_PIN GPIO_PIN_0

#define BSP_KEY1_RCU RCU_GPIOB // Key port clock
#define BSP_KEY1_PORT GPIOB // Key port
#define BSP_KEY1_PIN GPIO_PIN_3 // Key pin

#define BSP_KEY_EXTI_IRQN EXTI0_IRQn
#define BSP_KEY_EXTI_PORT_SOURCE EXTI_SOURCE_GPIOA
#define BSP_KEY_EXTI_PIN_SOURCE EXTI_SOURCE_PIN0
#define BSP_KEY_EXTI_LINE EXTI_0
#define BSP_KEY_EXTI_IRQHANDLER EXTI0_IRQHandler

void key_gpio_config(void);
void key_scan(void);
uint8_t KEY_Read(void);
void gearshift_show(void);

#endif
```
## 4. Ultrasonic ranging
! [QQ screenshot 20221220110715.png] The hc_04 module is used to measure the distance of the object in front of the car and display it on the OLED screen.
```
#include "bsp_ultrasonsic.h"
#include "stdio.h"
uint8_t Count_update;
static void ultrasonsic_gpio_config(void) //static can only be called below the file, not anywhere else
{
/*Enable GPIOB clock*/
rcu_periph_clock_enable(BSP_ULTRASONSIC_RCU);
/*Configure GPIOB clock mode*/
gpio_mode_set( BSP_ULTRASONSIC_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, BSP_ULTRASONSIC_TRIG_PIN); //Floating output
/*Configure GPIOB clock output*/
gpio_output_options_set(BSP_ULTRASONSIC_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, BSP_ULTRASONSIC_TRIG_PIN); //ULTRASONSIC_TRAG push-pull output

gpio_mode_set( BSP_ULTRASONSIC_PORT, GPIO_MODE_INPUT, GPIO_PUPD_PULLDOWN, BSP_ULTRASONSIC_ECHO_PIN); //Pull down
input gpio_bit_write(BSP_ULTRASONSIC_PORT,BSP_ULTRASONSIC_TRIG_PIN,RESET);//TRAG initial state is low
}
static void Ultras_TIM2_Init(uint16_t pre,uint16_t per)
{
timer_parameter_struct timere_initpara;
rcu_periph_clock_enable(BSP_ULTRASONSIC_TIMER_RCU);
rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4);
timer_deinit(BSP_ULTRASONSIC);
timere_initpara.prescaler =pre-1; /*!< prescaler value */
timere_initpara.alignedmode =TIMER_COUNTER_EDGE; /*!< aligned mode */
timere_initpara.counterdirection=TIMER_COUNTER_UP; /*!< counter direction */
timere_initpara.clockdivision =TIMER_CKDIV_DIV1; /*!< clock division value */
timere_initpara.period =per-1; /*!< period value */
timere_initpara.repetitioncounter=0;
timer_init(BSP_ULTRA SONSIC, &timere_initpara);
nvic_irq_enable(BSP_ULTRASONSIC_IRQ,3U, 2U);
timer_interrupt_enable(BSP_ULTRASONSIC,TIMER_INT_UP);
//timer_enable(BSP_ULTRASONSIC);
timer_interrupt_flag_clear(BSP_ULTRASONSIC,TIMER_INT_FLAG_UP); //Clear update interrupt to avoid an interrupt immediately after enabling it
timer_break_enable(BSP_ULTRASONSIC); //Enable timer update interrupt
timer_disable(BSP_ULTRASONSIC);
}
void Ultrasonic_Init(void)
{
ultrasonsic_gpio_config();
Ultras_TIM2_Init(200,1000); //1ms

}
void BSP_ULTRASONSIC_IRAHANDLER(void) //Timer interrupt, every 1ms count+1
{
if(timer_interrupt_flag_get(BSP_ULTRASONSIC,TIMER_INT_FLAG_UP)==SET)
{
timer_interrupt_flag_clear(BSP_ULTRASONSIC,TIMER_INT_FLAG_UP);
Count_update++;
}
}
static void timer_open(void) //Open timer
{
Count_update = 0;
timer_counter_value_config(BSP_ULTRASONSIC, 0);
timer_enable(BSP_ULTRASONSIC);//Enable timer
}
static void timer_close(void) //Close timer
{
timer_disable(BSP_ULTRASONSIC);
}

uint32_t GetEchoTimer(void)
{
uint32_t time= 0;
/*//When the echo signal is very long, the count value overflows and then repeats the count. OverCount uses interrupts to save the number of overflow times*/
time = Count_update*1000;//overCount is incremented every ++, which represents overCount milliseconds, and time is a microsecond
time+=timer_counter_read(BSP_ULTRASONSIC);//Get the count value in the TIM2 counter register, while calculating the echo signal time
timer_counter_value_config(BSP_ULTRASONSIC,0); //Clear the count value of the TIM2 counter register
delay_1ms(50);
return time;
}
float Hcsr04GetLength(void )
{
/*Measure 5 times of data and calculate the average value*/
float length = 0;
float t = 0;
float sum = 0;
uint16_t i = 0;
while(i != 5){
TRIG=1;
delay_1us(20);//Duration exceeds 10us
TRIG=0;
/*Echo sends a signal to wait for the echo signal*/
/*After inputting the square wave, the module will automatically transmit 8 40KHz sound waves. At the same time, the level of the echo pin (echo) will change from 0 to 1;
(The timer should be started at this time); When the ultrasonic wave returns and is received by the module, the level of the echo pin will change from 1 to 0;
(The timer should be stopped at this time), and the time recorded by the timer is
the total duration from the emission to the return of the ultrasonic wave;*/
while(ECHO == 0);//echo waits for echo
/*Start timer*/
timer_open();
i = i+1; //Each time an echo signal is received +1, and the average is calculated after 5 times
while(ECHO == 1);
/*Close the timer*/
timer_close();
/*Get the high level time of Echo*/
t = GetEchoTimer();
length = (float)t/58;//Unit: cm
sum += length;
}
length = sum/5;//Five times average
return length;
}
int a,b,c,d,e,f,g,h=0;
void bsp_distance_oled(void)
{
d=Hcsr04GetLength();
a=d/100;
b=(d%100)/10;
c=(d%10);
OLED_Clear();
OLED_ShowString(1,2,"distance:",3);
OLED_ShowNum(80,2,a,1,3);
OLED_ShowNum(86,2,b,1,3);
OLED_ShowNum(92,2,c,1,3);
}
```
``
#include "bsp_oled.h"
#define BSP_ULTRASONSIC_RCU RCU_GPIOD
#define BSP_ULTRASONSIC_PORT GPIOD

#define BSP_ULTRASONSIC _TRIG_PIN GPIO_PIN_1
#define BSP_ULTRASONSIC_ECHO_PIN GPIO_PIN_5

#define BSP_ULTRASONSIC_TIMER_RCU_TIMER4
#define BSP_ULTRASONSIC TIMER4
#define BSP_ULTRASONSIC_IRQ TIMER4_IRQn
#define BSP_ULTRASONSIC_IRAHANDLER TIMER4_IRQHandler

#define TRIG PDout(1)
#define ECHO PDin (5)

void Ultrasonic_Init(void);
void BSP_ULTRASONSIC_IRAHANDLER(void);
void Ultrasonic_Init(void);
uint32_t GetEchoTimer(void);
float HCSR04_Get_Distance(void);
float Hcsr04GetLength(void );
void bsp_distance_oled(void);
#endif
```
## 5. The Bluetooth module
uses the hc_05 module.
![QQ screenshot 20221220112426.png] ```
#include "bsp_hc.h"
#include "stdio.h"

uint8_t g_recv_buff_hc[USART_RECEIVE_LENGTH]; // Receive buffer
uint16_t g_recv_length_hc = 0; // Receive data length
uint8_t g_recv_complete_flag_hc = 0; // Receive data completion flag
void uart6_gpio_config(uint32_t band_rate)
{
/* Enable clock*/
rcu_periph_clock_enable(BSP_UART6_TX_RCU); // Enable serial port clock
rcu_periph_clock_enable(BSP_UART6_RX_RCU); // Enable port clock
rcu_periph_clock_enable(BSP_UART6_RCU); // Enable port clock

/* Configure GPIO multiplexing function*/
gpio_af_set(BSP_UART6_TX_PORT,BSP_UART6_AF,BSP_UART6_TX_PIN);
gpio_af_set(BSP_UART6_RX_PORT,BSP_UART6_AF,BSP_UART6_RX_PIN);

/* Configure GPIO mode*/ /
* Configure TX to multiplex mode pull-up mode*/ gpio_mode_set(BSP_UART6_TX_PORT,GPIO_MODE_AF,GPIO_PUPD_PULLUP,BSP_UART6_TX_PIN); /* Configure RX to multiplex mode pull-up mode*/
gpio_mode_set(BSP_UART6_RX_PORT, GPIO_MODE_AF,GPIO_PUPD_PULLUP,BSP_UART6_RX_PIN ); /* Configure TX to push-pull output 50MHZ */ gpio_output_options_set(BSP_UART6_TX_PORT,GPIO_OTYPE_PP,GPIO_OSPEED_50MHZ,BSP_UART6_TX_PIN); /* Configure RX to push-pull output 50MHZ */ gpio_output_options_set(BSP_UART6_RX_PORT,GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, BSP_UART6_RX_PIN); /* Configure serial port parameters*/ usart_deinit(BSP_UART6); // Reset serial portusart_baudrate_set(BSP_UART6,band_rate); // Set baud rateusart_parity_config(BSP_UART6,USART_PM_NONE); // No parity bitusart_word_length_set(BSP_UART6,USART_WL_8BIT); // 8-bit data bit usart_stop_bit_set(BSP_UART6,USART_STB_1BIT); // 1-bit stop bit /* Enable serial port */ usart_enable(BSP_UART6); // Enable serial port usart_transmit_config(BSP_UART6,USART_TRANSMIT_ENABLE); // Enable serial port sending usart_receive_config(BSP_UART6,USART_RECEIVE_ENABLE); // Enable serial port receiving /* Interrupt configuration */ nvic_irq_enable(BSP_UART6_IRQ, 2, 2); // Configure interrupt priority usart_interrupt_enable(BSP_UART6,USART_INT_RBNE); // Read data buffer non-empty interrupt and overflow error interrupt usart_interrupt_enable(BSP_UART6,USART_INT_IDLE); // Idle detection interrupt } void BSP_UART6_IRQHandler(void) { if(usart_interrupt_flag_get(BSP_UART6,USART_INT_FLAG_RBNE) == SET) // Receive buffer is not empty { g_recv_buff_hc[g_recv_length_hc++] = usart_data_receive(BSP_UART6); // Put the received data into the buffer } if(usart_interrupt_flag_get(BSP_UART6,USART_INT_FLAG_IDLE) == SET) // Frame interrupt detected { usart_data_receive(BSP_UART6); // Must read, the read value cannot be g_recv_buff_hc[g_recv_length_hc] = ''; // Data reception is completed, array end flag




































g_recv_complete_flag_hc = 1; // Reception completed
}
}
```
```
#ifndef _BSP_HC_H
#define _BSP_HC_H

#include "gd32f4xx.h"
#include "systick.h"

#define BSP_UART6_TX_RCU RCU_GPIOF // Port clock of serial port 6TX
#define BSP_UART6_RX_RCU RCU_GPIOF // Port clock of serial port 6RX
#define BSP_UART6_RCU RCU_UART6 // Clock of serial port 6
#define BSP_UART6_TX_PORT GPIOF // Port of serial port TX
#define BSP_UART6_RX_PORT GPIOF // Port of serial port RX#
define BSP_UART6_AF GPIO_AF_8 // Multiplexing function of serial port 6
#define BSP_UART6_TX_PIN GPIO_PIN_7 // Serial port 6TX pin
#define BSP_UART6_RX_PIN GPIO_PIN_6 // Serial port 6RX pin
#define BSP_UART6 UART6 // Serial port 6
#define BSP_UART6_IRQ UART6_IRQn // Serial port 6 interrupt
#define BSP_UART6_IRQHandler UART6_IRQHandler // Serial port 6 interrupt service function

/* Data length of serial port buffer*/
#define USART_RECEIVE_LENGTH 4096

extern uint8_t g_recv_buff_hc[USART_RECEIVE_LENGTH]; // Receive buffer
extern uint16_t g_recv_length_hc; // Receive data length
extern uint8_t g_recv_complete_flag_hc; // Receive completion flag

void uart6_gpio_config(uint32_t band_rate); // Configure serial port 6
#endif
```
## 6. Car light display
circuit design
! [QQ screenshot 20221220112759.png] Code part
```
#include "bsp_led.h"

void led_gpio_config(unsigned int RCU_LED,unsigned int PORT_LED,unsigned int PIN_LED)
{
/*Turn on GPIOD clock*/
rcu_periph_clock_enable(RCU_LED);
/*Configure GPIOD clock mode*/
gpio_mode_set( PORT_LED, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, PIN_LED);
/*Configure GPIOD clock output*/
gpio_output_options_set(PORT_LED, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, PIN_LED);

}
void led_left(void)
{

PGout(7)=0;
PAout(12)=0;
delay_1ms(100); PGout
( 3)
= 1; PAout( 12)= 1 ; delay_1ms(100) ; PGout(3)=0; 0; delay_1ms(100); PEout (3) =0 ; PAout (12) =1; delay_1ms(100) ; } void led_right(void) { PAout( 12)=0; PGout(7)=0; delay_1ms (100) ; delay_1ms(100); PDout(7)=0; PGout(3)=1; delay_1ms(100);


























PGout(7)=0;
PGout(3)=0;
delay_1ms(100);
PGout(7)=0;
delay_1ms(100);
}
void led_off(void)
{
PGout(7)=1;
PAout(12)= 1;
PEout(3)=0;
PDout(7)=0;
PGout(3)=0;
}
``
` ``
#ifndef _BSP_LED_H
#define _BSP_LED_H

#include "gd32f4xx.h"
#include "systick.h"
#include "systick.h"
#include "sys.h"
#include "bsp_ultrasonsic.h"

#define RCU_LED0 RCU_GPIOE
#define PORT_LED0 GPIOE
#define PIN_LED0 GPIO_PIN_3

#define RCU_LED1 RCU_GPIOD
#define PORT_LED1 GPIOD
#define PIN_LED1 GPIO_PIN_7

#define RCU_LED2 RCU_GPIOG
#define PORT_LED2 GPIOG
#define PIN_LED2 GPIO_PIN_3

#define RCU_LED3 RCU_GPIOA
#define PIN_LED3
GPIO_PIN_5

#define RCU_LED4 RCU_GPIOA
#define PORT_LED4 G PIOA
#define PIN_LED4 GPIO_PIN_12

#define RCU_LED5 RCU_GPIOG
#define PORT_LED5 GPIOG
#define PIN_LED5 GPIO_PIN_7

void led_gpio_config(unsigned int RCU_LED,unsigned int PORT_LED,unsigned int PIN_LED);
void led_left(void);
void led_right(void);
void led_off(void);
#endif
```
## 7. The voltage detection
circuit uses three 10K resistors for voltage division, then collects the voltage of the third resistor and displays the collected voltage on the OLED screen.
![QQ screenshot 20221220113241.png] ```
#include "bsp_adc.h"
#include "stdio.h"

#define DEBUG // Turning this on will enable the print information below adc_get_val

uint16_t adcValue;
uint16_t n,m,k =0;
uint16_t V_Value=0;
static void adc_gpio_init(void)
{
/* enable the clock */
rcu_periph_clock_enable(ADC_RCU);
/* configure GPIO port Additional functions need to be configured as GPIO_MODE_ANALOG */
gpio_mode_set(ADC_PORT, GPIO_MODE_ANALOG, GPIO_PUPD_NONE,ADC_PIN) ;
}
void adc_config(void)
{
/* enable ADC0 clock */
rcu_periph_clock_enable(RCU_ADC0);
/* config ADC clock */
adc_clock_config(ADC_ADCCK_PCLK2_DIV8);
/* reset ADC */
adc_deinit();
/* configure the ADC mode */
adc_sync_mode_config(ADC_SYNC_MODE_INDEPENDENT); // All ADCs work in independent mode

/* ADC contineous function disable */
adc_special_function_config (ADC0, ADC_CONTINUOUS_MODE, DISABLE); // Disable continuous mode
/* ADC scan mode disable */
adc_special_function_config(ADC0, ADC_SCAN_MODE, DISABLE); // Disable scan mode

/* ADC data alignment config */
adc_data_alignment_config(ADC0,ADC_DATAALIGN_RIGHT); // LSB alignment, low bit alignment

/* ADC channel length config */
adc_channel_length_config(ADC0,ADC_REGULAR_CHANNEL,1U); // ADC regular channel length is 1

/* enable ADC interface */
adc_enable(ADC0);
/* wait for ADC stability */
delay_1ms(1);
/* ADC calibration and reset calibration */
adc_calibration_enable(ADC0); // ADC calibration
/* wait for ADC stability */
delay_1ms(1);

/* adc pin initialization */
adc_gpio_init();
}
uint16_t adc_channel_sample(uint8_t channel)
{
/* ADC regular channel config */
adc_regular_channel_config(ADC0, 0U, channel, ADC_SAMPLETIME_15); // 15 sampling periods
/* ADC software trigger enable */
adc_software_trigger_enable(ADC0, ADC_REGULAR_CHANNEL); // ADC software trigger enable

/* wait the end of conversion flag */
while(!adc_flag_get(ADC0, ADC_FLAG_EOC));
/* clear the end of conversion flag */
adc_flag_clear(ADC0, ADC_FLAG_EOC);
/* return regular channel sample value */
return (adc_reg ular_data_read(ADC0));
}

void adc_get_val(void)
{
uint32_t adcValue_x=0;
uint32_t i,j,t;
uint16_t adc_get[7];
//adcValue = adc_channel_sample(ADC_CHANNEL_15); // sampling
for(i=0;i<7;i++)
{
adc_get[i]=adc_channel_sample(ADC_CHANNEL_15);
}
for(i=0;i<6;i++)
{
for(j=i+1;j<7;j++)
{
if(adc_get[j]>adc_get[i])
{
t=adc_get[i];
adc_get[i]=adc_get[j];
adc_get[j]=t;
}
} for (i=1;i<6;i++) { adcValue_x+=adc_get[i]; } adcValue=adcValue_x/5; V_Value = (adcValue
* 3)/4; n=V_Value/100; m=(V_Value%100)/10; k=(V_Value%10); #ifdef DEBUG OLED_ShowString(1,1,"ADC:", 3); OLED_ShowNum(30,1,n,1,3); OLED_ShowNum(36,1,m,1,3); OLED_ShowString(42,1,".",3); OLED_ShowNum(48,1,k,1,3); OLED_ShowString(58,1,"%",3); printf("adcValue is :%d ",adcValue); "adcValue is :%d ",V_Value); #endif } ``` ``` #ifndef _BSP_ADC_H #define _BSP_ADC_H #include "gd32f4xx.h" #include "systick.h" #include "bsp_usart.h" #include "bsp_oled.h" /* PB1 ADC01_IN9*/ #define ADC_RCU RCU_GPIOB





































#define ADC_PORT GPIOB
#define ADC_PIN GPIO_PIN_1

extern uint16_t adcValue;

void adc_config(void);
uint16_t adc_channel_sample(uint8_t channel);
void adc_get_val(void);

#endif
```
## 8.OLED screen
uses I2C to communicate
![QQ screenshot 20221220114136.png] ```
#include "bsp_i2c.h"
void HW_I2cInit(void)
{
rcu_periph_clock_enable(RCU_OLED_GPIO);//Enable peripheral clock function
rcu_periph_clock_enable(RCU_OLED_I2C);

gpio_af_set(PORT_OLED,I2C_OLED_AF,PIN_OLED_SDA); //Port multiplexing to serial port mode
gpio_af_set(PORT_OLED,I2C_OLED_AF,PIN_OLED_SCL);

gpio_mode_set(PORT_OLED, GPIO_MODE_AF, GPIO_PUPD_PULLUP, PIN_OLED_SDA); //Set GPIO mode
gpio_output_options_set(PORT_OLED, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, PIN_OLED_SDA); //Set GPIO output type and speed

gpio_mode_set(PORT_OLED, GPIO_MODE_AF, GPIO_PUPD_PULLUP, PIN_OLED_SCL);
gpio_output_options_set(PORT_OLED, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, PIN_OLED_SCL);

i2c_deinit(I2C_OLED);//Reset I2C_OLED
i2c_clock_config(I2C_OLED, 100000, I2C_DTCY_2);//Set baud
ratei2c_mode_addr_config(I2C_OLED, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, 0x78);//Set mode, transmission data length, host addressi2c_enable

(I2C_OLED);//Enable
peripheralsi2c_ack_config(I2C_OLED,I2C_ACK_ENABLE);
}
```
```
#ifndef _BSP_I2C_H_
#define _BSP_I2C_H_

#include "gd32f4xx.h"
#include "systick.h"

#define RCU_OLED_GPIO RCU_GPIOB
#define RCU_OLED_I2C RCU_I2C1

#define PORT_OLED GPIOB
#define PIN_OLED_SDA GPIO_PIN_11
#define PIN_OLED_SCL GPIO_PIN_10 #define
I2C_OLED_AF GPIO_AF_4
#define I2C_OLED I2C1

void HW_I2cInit(void);

#endif
`` `
``
#include "bsp_ oled.h"
#include "stdlib.h"
#include "OLED_Font.h"
#include "bsp_i2c.h"
//OLED video memory
//[0]0 1 2 3 ... 127
//[1]0
1 2 3 ... 127 //[2]0 1 2 3 ... 127
//[3]0 1 2 3 ... 127
//[4]0 1 2 3 ... 127
//[5]0 1 2 3 ... 127
//[6]0 1 2 3 ... 127
//[7]0 1 2 3 ... 127

/**********************************************
//Software IIC Start
**********************************************/
void IIC_Start(void)
{
OLED_SCLK_Set();
OLED_SDIN_Set();
OLED_SDIN_Clr();
_Clr();
}
/************************************************
//Software IIC Stop
**********************************************/
void IIC_Stop(void)
{
OLED_SCLK_Set();
OLED_SDIN_Clr();
OLED_SDIN_Set();
}
/**************************************** ******
//Software IIC Ack
*************************************** *******/
void IIC_Wait_Ack(void)
{
OLED_SCLK_Set() ;
OLED_SCLK_Clr();
}
/************************** **********************
// IIC Write byte
************************* *********************/
void Write_IIC_Byte(unsigned char IIC_Byte)
{
unsigned char i;
unsigned char m,da;
da=IIC_Byte;
OLED_SCLK_Clr();
for( i=0;i<8;i++)
{
m=da;
m=m&0x80;
if(m==0x80)
{
OLED_SDIN_Set();
}
else
OLED_SDIN_Clr();
da=da<<1;
OLED_SCLK_Set();
OLED_SCLK_Clr();
}
}
/**************************************** *******
// IIC Write Command
**************************************** ********/
void Write_IIC_Command(unsigned char IIC_Command)
{
#if S_I2C
IIC_Start();
Write_IIC_Byte(0x78); //Slave address,SA0=0
IIC_Wait_Ack();
Write_IIC_Byte(0x00); //write command
IIC_Wait_Ack();
Write_IIC_Byte(IIC_Command);
IIC_Wait_Ack();
IIC_Stop();
#else
while(i2c_flag_get(I2C1, I2C_FLAG_I2CBSY));
i2c_start_on_bus (I2C1);
while(!i2c_flag_get(I2C1, I2C_FLAG_SBSEND));//Enter host mode
i2c_master_addressing(I2C1, 0x78, I2C_TRANSMITTER);
while(!i2c_flag_get(I2C1, I2C_FLAG_ADDSEND));//Judge the address to send out
i2c_flag_clear (I2C1, I2C_FLAG_ADDSEND);//Clear ADDSEND bit
while(SET != i2c_flag_get(I2C1, I2C_FLAG_TBE)); //Enter data transmission state
i2c_data_transmit (I2C1, 0x00);
while(!i2c_flag_get(I2C1, I2C_FLAG_BTC));
i2c_data_transmit (I2C1, IIC_Command);
while(!i2c_flag_get(I2C1, I2C_FLAG_BTC) );
i2c_stop_on_bus (I2C1);
while(I2C_CTL0(I2C1)&0x0200);
#endif
}
/******************************** ****************
// IIC Write Data
******************************* ***************/
void Write_IIC_Data(unsigned char IIC_Data)
{
#if S_I2C
IIC_Start();
Write_IIC_Byte(0x78); //Slave address,SA0=0
IIC_Wait_Ack();
Write_IIC_Byte( 0x40); //write data
IIC_Wait_Ack();
Write_IIC_Byte(IIC_Data);
IIC_Wait_Ack();
IIC_Stop();
#else
while(i2c_flag_get(I2C1, I2C_FLAG_I2CBSY));
i2c_start_on_bus (I2C1);
while(!i2c_flag_get(I2C1, I2C_FLAG_SBSEND));//Enter host mode
i2c_master_addressing(I2C1, 0x78, I2C_TRANSMITTER);
while(!i2c_flag_get(I2C1, I2C_FLAG_ADDSEND));//Judge the address and send it out
i2c_flag_clear (I2C1, I2C_FLAG_ADDSEND);//Clear ADDSEND bit
while(SET != i2c_flag_get(I2C1, I2C_FLAG_TBE));//Enter data transmission state
i2c_data_transmit (I2C1, 0x40);
while(!i2c_flag_get(I2C1, I2C_FLAG_BTC));
i2c_data_transmit (I2C1, IIC_Data);
while(!i2c_flag_get(I2C1, I2C_FLAG_BTC));
i2c_stop_on_bus (I2C1);
while(I2C_CTL0(I2C1)&0x0200);
#endif
}
void OLED_WR_Byte(unsigned dat,unsigned cmd)
{
if(cmd)
{
Write_IIC_Data(dat);
}
else
{
Write _IIC_Command(dat);
}
}
/********************************************
//Fill Picture
********************************************/
void fill_picture(unsigned char fill_Data)
{
unsigned char m,n;
for(m=0;m<8;m++)
{
OLED_WR_Byte(0xb0+m,0); //page0-page1
OLED_WR_Byte(0x00,0); //low column start address
OLED_WR_Byte(0x10,0); //high column start address
for(n=0;n<128;n++)
{
OLED_WR_Byte(fill_Data,1);
}
}
}
/**********************************************
//Set Position
//Coordinate setting
**********************************************/
void OLED_Set_Pos(unsigned char x, unsigned char y)
{
OLED_WR_Byte(0xb0+y ,OLED_CMD);
OLED_WR_Byte(((x&0xf0)>>4)|0x10,OLED_CMD);
OLED_WR_Byte((x&0x0f),OLED_CMD);
}
/************************************************
//Turn on OLED display
//Turn on OLED display
**********************************************/
void OLED_Display_On(void)
{
OLED_WR_Byte(0X8D,OLED_CMD); //SET DCDC command
OLED_WR_Byte(0X14,OLED_CMD); //DCDC ON
OLED_WR_Byte(0XAF,OLED_CMD); //DISPLAY ON
}
/**********************************************
//Turn off OLED display
//Turn off OLED display
**********************************************/
void OLED_Display_Off(void)
{
OLED_WR_Byte(0X8D,OLED_CMD); //SET DCDC command
OLED_WR_Byte(0X10,OLED_CMD); //DCDC OFF
OLED_WR_Byte(0XAE,OLED_CMD); //DISPLAY OFF
}
/**************************************************
//Clear screen function, after clearing the screen, the whole screen is black!
**********************************************/
void OLED_Clear(void)
{
u8 i,n;
for(i=0;i<8;i++)
{
OLED_WR_Byte (0xb0+i,OLED_CMD); //Set page address (0~7)
OLED_WR_Byte (0x00,OLED_CMD); //Set display position—column low address
OLED_WR_Byte (0x10,OLED_CMD); //Set display position—column high address
for(n=0;n<128;n++)OLED_WR_Byte(0,OLED_DATA);
} //Update display
}
/**************************************************
//Screen light function, the whole screen lights up!
**********************************************/
void OLED_On(void)
{
u8 i,n;
for(i=0;i<8;i++)
{
OLED_WR_Byte (0xb0+i,OLED_CMD); //Set page address (0~7)
OLED_WR_Byte (0x00,OLED_CMD); //Set display position—column low
addressOLED_WR_Byte (0x10,OLED_CMD); //Set display position—column high addressfor
(n=0;n<128;n++)OLED_WR_Byte(1,OLED_DATA);
} //Update display
}
/**************************************************
//Display a character at the specified position, including partial characters
//x:0~127
//y:0~63
//mode:0, reverse display; 1, normal display
//chr: character to be displayed
//size: select font 16/12
**********************************************/
void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 Char_Size)
{
unsigned char c=0,i=0;
c=chr-' ';//Get the offset value, why do the offset to view ASCII Table
if(x>Max_Column-1){x=0;y=y+2;}
if(Char_Size ==16)
{
OLED_Set_Pos(x,y);
for(i=0;i<8;i++)
OLED_WR_Byte(F8X16[c*16+i],OLED_DATA);
OLED_Set_Pos(x,y+1);
for(i=0;i<8;i++)
O LED_WR_Byte(F8X16[c*16+i+8],OLED_DATA);
}
else
{
OLED_Set_Pos(x,y);
for(i=0;i<6;i++)
OLED_WR_Byte(F6x8[c][i],OLED_DATA);
}
}
/**********************************************
//m^n function
**********************************************/
u32 oled_pow( u8 m,u8 n)
{
u32 result=1;
while(n--)result*=m;
return result;
}
/**********************************************
//Display 2 numbers
//x:0~127
//y:0~63
//num: value (0~4294967295);
//len: number of digits
//size: font size
*******************************************/
void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size2)
{
u8 t,temp;
u8 enshow=0;
for(t=0;t {
temp=(num/oled_pow(10,len-t-1))%10;
if(enshow==0&&t<(len-1))
{
if(temp==0)
{
OLED_ShowChar(x+(size2/2)*t,y,' ',size2);
continue;
}
else
enshow=1;
}
OLED_ShowChar(x+(size2/2)*t,y,temp+'0',size2);
}
}
/**************************************************
//Display a character string
******************************************/
void OLED_ShowString(u8 x,u8 y,u8 *chr,u8 Char_Size)
{
unsigned char j=0;
while (chr[j]!='')
{
OLED_ShowChar(x,y,chr[j],Char_Size);
x+=8;
if(x>120){x=0;y+=2;}
j++;
}
}
/**************************************************
//Display Chinese characters
******************************************/
void OLED_ShowCHinese(u8 x,u8 y,u8 no)
{
u8 t,adder=0;
OLED_Set_Pos(x,y);
for(t=0;t<16;t++)
{
OLED_WR_Byte(Hzk[2*no][t],OLED_DATA);
adder+=1;
}
OLED_Set_Pos(x,y+1);
for(t=0;t<16;t++)
{
OLED_WR_Byte(Hzk[2*no+1][t],OLED_DATA);
adder+=1;
}
}
/**************************************************
Function description: Display BMP picture
//x0:0~127
//y0:0~63
128×64 starting point coordinates (x,y)
**********************************************/
void OLED_DrawBMP(unsigned char x0, unsigned char y0,unsigned char x1, unsigned char y1,unsigned char BMP[])
{
unsigned int j=0;
unsigned char x,y;

if(y1%8==0) y=y1/8;
else y=y1/8+1;
for(y=y0;y {
OLED_Set_Pos(x0,y);
for(x=x0;x {
OLED_WR_Byte(BMP[j++],OLED_DATA);
}
}
}
/************************************ **********
//Initialize SSD1306
**********************************************/
void OLED_Init(void)
{
OLED_WR_Byte(0xAE,OLED_CMD);//Turn off the display
OLED_WR_Byte(0x40,OLED_CMD);//---set low column address
OLED_WR_Byte(0xB0,OLED_CMD);//---set high column address
OLED_WR_Byte(0xC8,OLED_CMD);//-not offset

OLED_WR_Byte(0x81,OLED_CMD);//Set contrast OLED_WR_Byte(
0xff,OLED_CMD);

OLED_WR_Byte(0xa1,OLED_CMD);//Segment redirection setting
OLED_WR_Byte(0xa6,OLED_CMD);//

OLED_WR_Byte( 0xa8,OLED_CMD);//Set the number of drive channels
OLED_WR_Byte(0x1f,OLED_CMD);

OLED_WR_Byte(0xd3,OLED_CMD) ;
OLED_WR_Byte

(0x00,OLED_CMD); OLED_WR_Byte(0xd5,OLED_CMD)
; OLED_WR_Byte(0xf0,OLED_CMD );

(0xd9,OLED_CMD);
OLED_WR_Byte(0x22,OLED_CMD);

OLED_WR_Byte(0xda,OLED_CMD);
OLED_WR_Byte(0x02,OLED_CMD); OLED_WR_Byte

(0xdb,OLED_CMD); OLED_WR_Byte(0x49,OLED_CMD);
OLED_WR_Byte(0x8d,OLED_CMD); OLED_WR_Byte(

0x14,OLED_CMD)
; _Byte

(0xaf,OLED_CMD);
OLED_Clear ();
}
```
```
#ifndef __BSP_OLED_H
#define __BSP_OLED_H

#include "gd32f4xx.h"
#include "systick.h"
#include "bsp_i2c.h"
#include "stdlib.h"

#define OLED_MODE 0
#define SIZE 8
#define XLevelL 0x00
#define XLevelH 0x10
#define Max_Column 128
#define Max_Row 32
#define Brightness 0xFF
#define X_WIDTH 128
#define Y_WIDTH 32
//-----------------OLED software I2C port definition--------- -------
#define OLED_SCLK_Clr() gpio_bit_reset(GPIOA, GPIO_PIN_2) //Set the pin to high level //SCL IIC interface clock signal
#define OLED_SCLK_Set() gpio_bit_set(GPIOA, GPIO_PIN_2)

#define OLED_SDIN_Clr( ) gpio_bit_reset(GPIOA, GPIO_PIN_3) //SCL IIC interface data signal
#define OLED_SDIN_Set() gpio_bit_set(GPIOA, GPIO_PIN_3)

#define OLED_CMD 0 //Write command
#define OLED_DATA 1 //Write data

#define S_I2C 0//Software IIC or hardware IIC switch

#define u8 unsigned char
#define u32 unsigned int

//OLED control function
void fill_picture(unsigned char fill_Data);
void IIC_Start(void);
void IIC_Stop(void);
void IIC_Wait_Ack(void );
void Write_IIC_Command(unsigned char IIC_Command);
void Write_IIC_Data(unsigned char IIC_Data
); void Write_IIC_Byte(unsigned char IIC_Byte);

void OLED_WR_Byte(unsigned dat,unsigned cmd);
void OLED_Display_On(void);
void OLED_Display_Off(void);
void OLED_Init (void);
void OLED_Clear(void);
void OLED_DrawPoint(u8 x,u8 y,u8 t);
void OLED_Fill(u8 x1,u8 ​​y1,u8 x2,u8 y2,u8 dot);
void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 Char_Size);
void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size);
void OLED_ShowString(u8 x,u8 y, u8 *p,u8 Char_Size);
void OLED_Set_Pos(unsigned char x, unsigned char y);
void OLED_ShowCHinese(u8 x,u8 y,u8 no);
void OLED_DrawBMP(unsigned char x0,
unsigned char y0,
unsigned char x1,
unsigned char y1,
unsigned char BMP[]);



#endif

````
## 9. Driving circuit
The driving circuit uses the driving chip RZ7889 to drive
! [QQ screenshot 20221220150331.png] Chip description
! [QQ screenshot 20221220150525.png] Because the text is too long, it is not allowed, so the code is attached.
## 10. Development board Wiring
![QQ screenshot 20221220152011.png] ## 11. Bluetooth software page
![Screenshot_20221220_152622.jpg] Bluetooth setting software
![QQ screenshot 20221220152833.png] Connect the Bluetooth module to ch_340, TXD to RXD, RXD to TXD, then press and hold the button of the Bluetooth module and power it on, then you can use the software to set the Bluetooth module.
## Summary
Some errors were found during the verification of the car, which have been modified in the original schematic and successfully verified on the original car.
参考设计图片
×
 
 
Search Datasheet?

Supported by EEWorld Datasheet

Forum More
Update:2025-06-19 16:33:13

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
community

Robot
development
community

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号