时光正好 · 2022年12月01日 · 辽宁

【GD32F427开发板试用】-油液颗粒检测仪系统(简单版)

前言

  • 很高兴入选兆易创新GD32F427开发板试用名单,该系列采用Arm® Cortex®-M4内核,处理器主频高达240MHz,可支持算法复杂度更高的嵌入式应用,并具备更快速的实时处理能力。GD32F4新产品配备了512KB到3072KB片上Flash,代码执行零等待区提升至1024KB。还配备了256KB到768KB的SRAM,以业界领先的大容量存储优势支持高级计算、通信网络、人机界面等工业及消费类多元化应用场景。
  • 回到正题,本次开发设计的试验为:油液颗粒检测仪系统(简单版),能够实现OLED显示、舵机控制、ADC电压显示、串口等功能。

效果图

图片1.png

系统框架

QQ截图20221201121312.png

软件设计

1.OLED显示

使用SPI,1.3寸OLED显示。

extern unsigned char BMP1[];            //OLED字模
void OLED_display_info()//显示数据显示界面,电压值,采样值
{
    OLED_ShowCHinese(10,0,9,16,1);        
    OLED_ShowCHinese(28,0,10,16,1);        
    OLED_ShowCHinese(46,0,58,16,1);        
    OLED_ShowCHinese(64,0,59,16,1);        
    OLED_ShowCHinese(82,0,60,16,1);        
    OLED_ShowCHinese(100,0,61,16,1);   
    delay_1ms(200);
    OLED_ShowCHinese(0,25,6,16,1); 
    OLED_ShowCHinese(18,25,7,16,1); 
    OLED_ShowCHinese(36,25,8,16,1); 
    OLED_ShowString(54,25,":",16,1);
    delay_1ms(200);
    OLED_ShowCHinese(0,48,9,16,1); 
    OLED_ShowCHinese(18,48,10,16,1); 
    OLED_ShowCHinese(36,48,11,16,1); 
    OLED_ShowString(54,48,":",16,1);
    delay_1ms(200);
    OLED_Refresh();//更新显存到OLED,重要
}
void my_testA0(void)//油液颗粒检测仪//首页
{
        OLED_Clear(0);
        OLED_ShowCHinese(5,16,49,16,1); 
        OLED_ShowCHinese(23,16,50,16,1); 
        OLED_ShowCHinese(41,16,51,16,1); 
        OLED_ShowCHinese(59,16,52,16,1); 
        OLED_ShowCHinese(77,16,53,16,1); 
        OLED_ShowCHinese(95,16,54,16,1); 
        OLED_ShowCHinese(113,16,55,16,1); 
        OLED_Refresh();
}
void my_testB1(void)//第一层第一
{
    OLED_Clear(0);
    OLED_ShowString(100,0,"<",16,1);

    OLED_ShowCHinese(0,0,12,16,1);
    OLED_ShowCHinese(20,0,13,16,1);
    OLED_ShowCHinese(40,0,14,16,1);
    OLED_ShowCHinese(60,0,15,16,1);
    
    OLED_ShowString(0,16,"1.",16,1);
    OLED_ShowCHinese(20,16,16,16,1);
    OLED_ShowCHinese(40,16,17,16,1);
    OLED_ShowCHinese(60,16,14,16,1);
    OLED_ShowCHinese(80,16,15,16,1);
    
    OLED_ShowString(0,32,"2.",16,1);
    OLED_ShowCHinese(20,32,18,16,1);
    OLED_ShowCHinese(40,32,19,16,1);
    OLED_ShowCHinese(60,32,14,16,1);
    OLED_ShowCHinese(80,32,15,16,1);
    
    OLED_ShowString(0,48,"3.",16,1);
    OLED_ShowCHinese(20,48,44,16,1);
    OLED_ShowCHinese(40,48,45,16,1);
    OLED_ShowCHinese(60,48,14,16,1);
    OLED_ShowCHinese(80,48,15,16,1);
    OLED_Refresh();
    }
void my_testB2(void)//第一层第二
{
    OLED_Clear(0);
    OLED_ShowString(100,16,"<",16,1);

    OLED_ShowCHinese(0,0,12,16,1);
    OLED_ShowCHinese(20,0,13,16,1);
    OLED_ShowCHinese(40,0,14,16,1);
    OLED_ShowCHinese(60,0,15,16,1);
    
    OLED_ShowString(0,16,"1.",16,1);
    OLED_ShowCHinese(20,16,16,16,1);
    OLED_ShowCHinese(40,16,17,16,1);
    OLED_ShowCHinese(60,16,14,16,1);
    OLED_ShowCHinese(80,16,15,16,1);
    
    OLED_ShowString(0,32,"2.",16,1);
    OLED_ShowCHinese(20,32,18,16,1);
    OLED_ShowCHinese(40,32,19,16,1);
    OLED_ShowCHinese(60,32,14,16,1);
    OLED_ShowCHinese(80,32,15,16,1);
    
    OLED_ShowString(0,48,"3.",16,1);
    OLED_ShowCHinese(20,48,44,16,1);
    OLED_ShowCHinese(40,48,45,16,1);
    OLED_ShowCHinese(60,48,14,16,1);
    OLED_ShowCHinese(80,48,15,16,1);
    OLED_Refresh();
}
void my_testB3(void)//第一层第三
{
    OLED_Clear(0);
    OLED_ShowString(100,32,"<",16,1);

    OLED_ShowCHinese(0,0,12,16,1);
    OLED_ShowCHinese(20,0,13,16,1);
    OLED_ShowCHinese(40,0,14,16,1);
    OLED_ShowCHinese(60,0,15,16,1);
    
    OLED_ShowString(0,16,"1.",16,1);
    OLED_ShowCHinese(20,16,16,16,1);
    OLED_ShowCHinese(40,16,17,16,1);
    OLED_ShowCHinese(60,16,14,16,1);
    OLED_ShowCHinese(80,16,15,16,1);
    
    OLED_ShowString(0,32,"2.",16,1);
    OLED_ShowCHinese(20,32,18,16,1);
    OLED_ShowCHinese(40,32,19,16,1);
    OLED_ShowCHinese(60,32,14,16,1);
    OLED_ShowCHinese(80,32,15,16,1);
    
    OLED_ShowString(0,48,"3.",16,1);
    OLED_ShowCHinese(20,48,44,16,1);
    OLED_ShowCHinese(40,48,45,16,1);
    OLED_ShowCHinese(60,48,14,16,1);
    OLED_ShowCHinese(80,48,15,16,1);
    OLED_Refresh();
}
    typedef struct
{
 unsigned char current;//现在所在页面层数    
 unsigned char down;//向下翻
 unsigned char enter;//进入功能
void(*current_operation)();//执行函数。显示图片
}key_table;
key_table table[30]=
{
//首页
    {0,0,1,(*my_testA0)},
//第一层
    {1,2, 1,(*my_testB1)},//所有模式
    {2,3, 7,(*my_testB2)},//冲洗模式
    {3,4, 8,(*my_testB3)},//显示模式
    {4,5, 9,(*my_testB4)},//串口模式
    {5,6, 10,(*my_testB5)},//其他信息
    {6,1, 1,(*my_testB6)},//返回
//第二层
    {7,7,2,(*my_testC5)},//电机转动
    {8,8,3,(*my_testC6)},//电压值显示  
    {9,9,4,(*my_testC7)},//串口开启 
    {10,11,12,(*my_testC8)},//版本信息
    {11,10,5,(*my_testC9)},//返回 
};
    void(*current_operation_index)();
    unsigned char  func_index =0;
    unsigned char last_index =127;

其余显示部分省略,可通过PCtoLCD2002软件,实现图片的代码转换。OLED字库使用SPI通用字库

2.按键

使用板子自带的按键,长按确定,短按为菜单调整。

#define    KEY_Press 0        //按键按下
#define    KEY_Pull    1      //按键放开
#define LongPressCount 80 //超过100*5ms=500ms,算做长按
//****************************按键返回数值
#define KEY1Value 10      //短按
#define KEY1LongValue 11  //长按
void Scan_Keys_OLED()
    {
        uint8_t CountPressTime=0;//长按时间计数
         if(gpio_input_bit_get(GPIOA, GPIO_PIN_0)== RESET)//确认
        {
              delay_1ms(10);
        if(gpio_input_bit_get(GPIOA, GPIO_PIN_0)== RESET)
        {
                    delay_1ms(10);
                    if(gpio_input_bit_get(GPIOA, GPIO_PIN_0)== RESET)
        {
                    gpio_bit_set(GPIOC, GPIO_PIN_13);
                    delay_1ms(100);
                    gpio_bit_reset(GPIOC, GPIO_PIN_13);                
                    while(gpio_input_bit_get(GPIOA, GPIO_PIN_0)== RESET)
                    {
                        delay_1ms(10);    
                        CountPressTime++;    
                    }
                    if(CountPressTime>LongPressCount)
            {
                CountPressTime=0;
                func_index = table[func_index].enter;    //确认
            }
            else //如果是短按,返回短按的数值
                func_index = table[func_index].down;    //下
                  }
         }
                }
        if (func_index != last_index)
            {
                    current_operation_index = table[func_index].current_operation;
                (*current_operation_index)();//执行当前操作函数
                    last_index = func_index;
            }
        };

3.PWM

使用PWM控制电机旋转。

#define BSP_PWM_RCU     RCU_GPIOA               // PWM端口时钟
#define BSP_PWM_PORT    GPIOA                                     // PWM端口
#define BSP_PWM_PIN     GPIO_PIN_5              // PWM引脚
#define BSP_PWM_AF      GPIO_AF_1                                // PWM引脚复用
#define BSP_PWM_TIMER_RCU      RCU_TIMER1    // 定时器时钟
#define BSP_PWM_TIMER           TIMER1        // 定时器
#define BSP_PWM_CHANNEL  TIMER_CH_0    // 定时器通道
static void pwm_gpio_config(void)
{
      /* 使能时钟 */
    rcu_periph_clock_enable(BSP_PWM_RCU);
    /* 配置GPIO的模式 */
gpio_mode_set(BSP_PWM_PORT,GPIO_MODE_AF,GPIO_PUPD_NONE,BSP_PWM_PIN);
    /* 配置GPIO的输出 */
gpio_output_options_set(BSP_PWM_PORT,GPIO_OTYPE_PP,GPIO_OSPEED_50MHZ,BSP_PWM_PIN);
    /* 配置GPIO的复用 */
    gpio_af_set(BSP_PWM_PORT,BSP_PWM_AF,BSP_PWM_PIN);    
}
void pwm_config(uint16_t pre,uint16_t per)
{
    timer_parameter_struct timere_initpara;  // 定义定时器结构体
    timer_oc_parameter_struct timer_ocintpara; //比较输出结构体
    pwm_gpio_config();        // 使能GPIO
    rcu_periph_clock_enable(BSP_PWM_TIMER_RCU);// 开启定时器时钟
    rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4);// 配置
    /* 配置定时器参数 */
    timer_deinit(BSP_PWM_TIMER);        // 复位定时器
    timere_initpara.prescaler = pre-1;   // 时钟预分频值 PSC_CLK= 200MHZ / 200 = 1MHZ       
    timere_initpara.alignedmode = TIMER_COUNTER_EDGE; // 对齐   
    timere_initpara.counterdirection = TIMER_COUNTER_UP; // 计数 
    timere_initpara.period = per-1; //T = 10000 * 1MHZ = 10ms  f = 100HZ   
    timere_initpara.clockdivision = TIMER_CKDIV_DIV1; //分频因子
    /* 只有高级定时器才有 配置为x,就重复x+1次进入中断 */
    timere_initpara.repetitioncounter = 0;  // 重复计数器 0-255  
    timer_init(BSP_PWM_TIMER,&timere_initpara);// 初始化定时器
    /* 配置输出结构体 */
    timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_HIGH; // 极性
    timer_ocintpara.outputstate = TIMER_CCX_ENABLE;        
    /* 配置定时器输出功能 */  timer_channel_output_config(BSP_PWM_TIMER,BSP_PWM_CHANNEL,&timer_ocintpara);
    /* 配置占空比 */
timer_channel_output_pulse_value_config(BSP_PWM_TIMER,BSP_PWM_CHANNEL,0);    // 配置定时器通道输出脉冲值
timer_channel_output_mode_config(BSP_PWM_TIMER,BSP_PWM_CHANNEL,TIMER_OC_MODE_PWM0);                // 配置定时器通道输出比较模式
timer_channel_output_shadow_config(BSP_PWM_TIMER,BSP_PWM_CHANNEL,TIMER_OC_SHADOW_DISABLE);// 配置定时器通道输出影子寄存器
    /* 只有高级定时器使用 */
    timer_auto_reload_shadow_enable(BSP_PWM_TIMER);
     /* 使能定时器 */
    timer_enable(BSP_PWM_TIMER);
}
void pwm_breathing_lamp(void)
{
    static uint8_t direct = 0; // 方向
    static uint16_t value = 0; // 脉冲值
    
    if(direct == 0)             // 逐渐变亮 
    {
        value += 400;         // 值越大 
        if(value > 10000)         
           direct = 1;         // 改变方向
    }else // 逐渐变暗
    { 
        value -= 400;          // 值越小
        if(value <= 0)
            direct = 0;
    }
timer_channel_output_pulse_value_config(BSP_PWM_TIMER,BSP_PWM_CHANNEL,value); // 配置定时器通道输出脉冲值
    delay_1ms(50);             // 延时50ms
}

4.ADC

使用外部光敏电阻模拟电压变化,使用ADC读取数值并计算电压。外部可接传感器电压。

/***********************
采样次数  30
ADC通道  4
***********************/
uint16_t gt_adc_val[30][4];  //DMA缓冲区    
// ADC Init
void ADC_DMA_Init(void)
{
    /* DMA初始化功能结构体定义 */
    dma_single_data_parameter_struct dma_single_data_parameter;
    /* 使能GPIOC组时钟 */
    rcu_periph_clock_enable(RCU_GPIOC);        
    /* 使能ADC0时钟 */
    rcu_periph_clock_enable(RCU_ADC0);        
    /* 使能DMA1时钟 */
    rcu_periph_clock_enable(RCU_DMA1);
    /*    配置ADC时钟    */ 
    adc_clock_config(ADC_ADCCK_PCLK2_DIV4);    
    /*    配置PC1 PC2 PC3 PC4 为浮空模拟输入模式    */
    gpio_mode_set(GPIOC, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_1); // PC1 : ADC012_IN11 
    gpio_mode_set(GPIOC, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_2); // PC2 : ADC012_IN12 
    gpio_mode_set(GPIOC, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_3); // PC3 : ADC012_IN13 
    gpio_mode_set(GPIOC, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_4); // PC4 : ADC012_IN14 
    /*    配置ADC为独立模式    */
    adc_sync_mode_config(ADC_SYNC_MODE_INDEPENDENT);
    /*    使能连续转换模式    */
    adc_special_function_config(ADC0, ADC_CONTINUOUS_MODE, ENABLE);
    /*    使能扫描模式    */
    adc_special_function_config(ADC0, ADC_SCAN_MODE, ENABLE);
    /*    数据右对齐    */        
    adc_data_alignment_config(ADC0, ADC_DATAALIGN_RIGHT);
    /*    ADC0设置为规则组  一共使用2个通道        */  
    adc_channel_length_config(ADC0, ADC_ROUTINE_CHANNEL, 4);
    /*    ADC规则通道配置:ADC0的通道11,12,13,14的扫描顺序分别为0,1,2,3;采样时间:15个周期        */  
    /*    DMA开启之后 gt_adc_val[x][0] = PC1的数据   gt_adc_val[x][3] = PC4的数据  x的范围0-29 */
    adc_routine_channel_config(ADC0, 0, ADC_CHANNEL_11, ADC_SAMPLETIME_15);//PC1
    adc_routine_channel_config(ADC0, 1, ADC_CHANNEL_12, ADC_SAMPLETIME_15);//PC2
    adc_routine_channel_config(ADC0, 2, ADC_CHANNEL_13, ADC_SAMPLETIME_15);//PC3
    adc_routine_channel_config(ADC0, 3, ADC_CHANNEL_14, ADC_SAMPLETIME_15);//PC4
     /*    ADC0设置为12位分辨率        */  
    adc_resolution_config(ADC0, ADC_RESOLUTION_12B); 
    /*    ADC外部触发禁用, 即只能使用软件触发        */  
    adc_external_trigger_config(ADC0, ADC_ROUTINE_CHANNEL, EXTERNAL_TRIGGER_DISABLE);
    /*    使能规则组通道每转换完成一个就发送一次DMA请求        */  
    adc_dma_request_after_last_enable(ADC0);  
    /*    使能DMA请求        */  
    adc_dma_mode_enable(ADC0);
    /*    使能DMA        */      
    adc_enable(ADC0);
    /*    等待ADC稳定        */  
    delay_1ms(1);
    /*    开启ADC自校准        */
    adc_calibration_enable(ADC0); 
    /*    清除 DMA通道0 之前配置     */
    dma_deinit(DMA1, DMA_CH0);
    /*    DMA初始化配置     */
    dma_single_data_parameter.periph_addr = (uint32_t)(&ADC_RDATA(ADC0));        //设置DMA传输的外设地址为ADC0基地址
    dma_single_data_parameter.periph_inc = DMA_PERIPH_INCREASE_DISABLE;            //关闭外设地址自增
    dma_single_data_parameter.memory0_addr = (uint32_t)(gt_adc_val);                //设置DMA传输的内存地址为 gt_adc_val数组
    dma_single_data_parameter.memory_inc = DMA_MEMORY_INCREASE_ENABLE;            //开启内存地址自增(因为不止一个通道)
    dma_single_data_parameter.periph_memory_width = DMA_PERIPH_WIDTH_16BIT;    //传输的数据位 为 16位
    dma_single_data_parameter.direction = DMA_PERIPH_TO_MEMORY;                            //DMA传输方向为 外设往内存
    dma_single_data_parameter.number = 4*30;                                        //传输的数据长度为:4个通道 * 每个通道采集30次
    dma_single_data_parameter.priority = DMA_PRIORITY_HIGH;                            //设置高优先级
    dma_single_data_mode_init(DMA1, DMA_CH0, &dma_single_data_parameter);    //将配置保存至DMA1的通道0
    /*    DMA通道外设选择        */
    /*    数据手册的195页根据PERIEN[2:0]值确定第三个参数,例是100 则为DMA_SUBPERI4      例是010 则为DMA_SUBPERI2     */
    /*    我们是ADC0功能,PERIEN[2:0]值为000,故为DMA_SUBPERI0*/
    dma_channel_subperipheral_select(DMA1, DMA_CH0, DMA_SUBPERI0);
    /*    使能DMA1通道0循环模式        */
    dma_circulation_enable(DMA1, DMA_CH0);
    /*    启动DMA1的通道0功能        */
    dma_channel_enable(DMA1, DMA_CH0); 
    /*    开启软件触发ADC转换        */
    adc_software_trigger_enable(ADC0, ADC_ROUTINE_CHANNEL); 
}
//对DMA保存的数据进行平均值计算后输出
//传入参数:CHx 第几个扫描的数据 
// 根据前面的配置得知:PC1为0 PC2为1 PC3为2 PC4为3
//返回数据:对应扫描的ADC值
unsigned int Get_Adc_Dma_Value(char CHx)
{
    unsigned char i = 0;
    unsigned int AdcValue = 0;
    /* 因为采集30次,故循环30次 */
    for(i=0;i<30;i++)
    {
        /*    累加    */
        AdcValue+=gt_adc_val[i][CHx];
    }
    /* 求平均值 */
    AdcValue=AdcValue/30;
    return AdcValue;
}
extern uint16_t gt_adc_val[30][4];  //DMA缓冲区
/************************
void ADC_Init(void);
unsigned int Get_ADC_Value(void);
**************************/
unsigned int Get_Adc_Dma_Value(char CHx);
uint8_t str_buff[64];    
uint16_t ADC_Value = 0;                      //ADC临时值
uint16_t ADC_Volt = 0;                         //ADC临时值
    unsigned char temp_buff[200]; 
    unsigned int  show_buff[4];
    void OLED_display_dat()//更新ADC采样数据与换算结果
{
        sprintf((char *)temp_buff, "%4d",show_buff[0]);            
    OLED_ShowString1(64,3,(uint8_t *)temp_buff);
        ADC_Value=show_buff[0];
        ADC_Volt = ADC_Value * 330 / 4096;   //2的8次方256,12次方4096,16次方65536
    sprintf((char*)temp_buff, "%d.%d%dV", ADC_Volt/100, (ADC_Volt%100)/10, ADC_Volt%10);    
        OLED_ShowString1(64,6,(uint8_t *)temp_buff);
}

5.串口

串口可打印参数

void usart_gpio_config(uint32_t band_rate)
{
  /* 开启时钟 */
    rcu_periph_clock_enable(BSP_USART_TX_RCU); 
    rcu_periph_clock_enable(BSP_USART_RX_RCU); 
    rcu_periph_clock_enable(BSP_USART_RCU); 
    
    /* 配置GPIO复用功能 */
  gpio_af_set(BSP_USART_TX_PORT,BSP_USART_AF,BSP_USART_TX_PIN);    
    gpio_af_set(BSP_USART_RX_PORT,BSP_USART_AF,BSP_USART_RX_PIN);    
    
    /* 配置GPIO的模式 */
    /* 配置TX为复用模式 上拉模式 */
gpio_mode_set(BSP_USART_TX_PORT,GPIO_MODE_AF,GPIO_PUPD_PULLUP,BSP_USART_TX_PIN);
    /* 配置RX为复用模式 上拉模式 */
    gpio_mode_set(BSP_USART_RX_PORT, GPIO_MODE_AF,GPIO_PUPD_PULLUP,BSP_USART_RX_PIN);
    
    /* 配置TX为推挽输出 50MHZ */
    gpio_output_options_set(BSP_USART_TX_PORT,GPIO_OTYPE_PP,GPIO_OSPEED_50MHZ,BSP_USART_TX_PIN);
    /* 配置RX为推挽输出 50MHZ */
    gpio_output_options_set(BSP_USART_RX_PORT,GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, BSP_USART_RX_PIN);

    /* 配置串口的参数 */
    usart_deinit(BSP_USART);
    usart_baudrate_set(BSP_USART,band_rate);
    usart_parity_config(BSP_USART,USART_PM_NONE);
    usart_word_length_set(BSP_USART,USART_WL_8BIT);
    usart_stop_bit_set(BSP_USART,USART_STB_1BIT);

  /* 使能串口 */
    usart_enable(BSP_USART);
    usart_transmit_config(BSP_USART,USART_TRANSMIT_ENABLE);
}

/* 发送函数 */
void usart_send_data(uint8_t ucch)
{
    usart_data_transmit(BSP_USART,(uint8_t)ucch);
    while(RESET == usart_flag_get(BSP_USART,USART_FLAG_TBE));
}
/* 串口发送字符串 */
void usart_send_string(uint8_t *ucstr)
{
    while(ucstr && *ucstr)
    {
      usart_send_data(*ucstr++);
    }

主函数

主函数的配置

    systick_config();
    rcu_periph_clock_enable(RCU_GPIOC);
    gpio_mode_set(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_6);
    gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_6);
        //KEY_A0初始化
    rcu_periph_clock_enable(RCU_GPIOA);
    gpio_mode_set(GPIOA, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN_0);
        //BEEP_C13初始化
     rcu_periph_clock_enable(RCU_GPIOC);
    gpio_mode_set(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_13);
    gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_13);
      gpio_bit_set(GPIOC, GPIO_PIN_6);
    delay_1ms(1000);
    gpio_bit_reset(GPIOC, GPIO_PIN_6);
    delay_1ms(1000);
        OLED_Init();
        OLED_ColorTurn(0);    //0正常显示 1 黑白相反,反色显示        
        OLED_Clear(1);//显示全部像素
        delay_1ms(500);
        OLED_Clear(0);//黑屏
        OLED_ShowPicture(0,0,128,64,BMP1,1);
        OLED_Refresh();//更新显存到OLED,重要!
        delay_1ms(1000);                
        OLED_Clear(0);    
     rcu_periph_clock_enable(RCU_GPIOA);
    gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_1);
    gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_1);
    pwm_config(200,10000);                         // PWM初始化
    nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2);  // 优先级分组
    systick_config();                                                  ADC_DMA_Init();         

While函数

    Scan_Keys_OLED();
    switch(func_index)               //判断系统状态
    {
    case 7:                        
        pwm_breathing_lamp();       // PWM函数
    break;
        case 8: 
        show_buff[0] = Get_Adc_Dma_Value(0);//根据扫描顺序得知数组[0] = PC1的数据
        OLED_display_dat();
        OLED_display_info();
        break;
        case 9:   
        delay_1ms(500);
        break;
    }        
                        

视频演示

https://www.bilibili.com/vide...

推荐阅读
关注数
10711
内容数
187
中国高性能通用微控制器领域的领跑者兆易创新GD系列芯片技术专栏。
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息