AD\Test\2025\October\TestCIU32F003.SchDoc

 

01 CIU32F003开发文档


一、测试电路板

  如下是用于测试CIU32F003的电路设计。 电路班使用单面铺设可以完成相应的实验。

GM00002409833_1920_1080.MP4|_-2

二、CIU32 BSP 文件

  根据 CIU32单片机演示程序, 测试修改之后, 形成下面可以使用宏定义重新配置的文件。 需要使用某一个硬件模块的时候, 可以在 CIU32.H 最前面的 define 命令中, 将相应的模块定义为 1 即可。

  需要说明的是, UART2的功能不能够使用。 一旦启动 UART2, 芯片就无法下载软件了。 现在具体原因还不得而知。

1、Head

/*
**==============================================================================
** CIU32.H:            -- by Dr. ZhuoQing, 2025-10-13
**
**  Description:
**
**==============================================================================
*/
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//==============================================================================

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void CIU32F003Init(void);

//------------------------------------------------------------------------------
void CIU32F003PortInit(void);

//------------------------------------------------------------------------------
//   MISCELLANEOUS FUNCTIONS
void Delay(__IO uint32_t nCount);
void WaitTime(uint32_t nTime);

void GPIOSetOutput(uint32_t pclk, GPIO_t * port, uint16_t pin);
void GPIOSetOutputOD(uint32_t pclk, GPIO_t * port, uint16_t pin);
void GPIOSetInput(uint32_t pclk, GPIO_t * port, uint16_t pin);
void GPIOSetInputPU(uint32_t pclk, GPIO_t * port, uint16_t pin);
void GPIOSetInputPD(uint32_t pclk, GPIO_t * port, uint16_t pin);

//------------------------------------------------------------------------------
//        ACTION FUCNTION

//------------------------------------------------------------------------------

//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
//==============================================================================
//              UART SUBROUTINE
//------------------------------------------------------------------------------

void UARTInit(void);

void UARTSendChar(unsigned char c);
unsigned char UARTReceChar(unsigned char * pc);

//------------------------------------------------------------------------------

extern __IO uint8_t g_ucUARTHead, g_ucUARTTail;
extern uint8_t g_ucUARTBuffer[UART_BUFFER];

//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
//__ATTRIBUTES int putchar(int ch);

//__ATTRIBUTES int getchar(void);
int getchar(void);

//==============================================================================
//              UART2 FUNCTIONS
//------------------------------------------------------------------------------
void UART2Init(void);
void UART2SendChar(unsigned char c);
unsigned char UART2ReceChar(unsigned char * pc);

extern __IO uint8_t g_ucUART2Head, g_ucUART2Tail;
extern uint8_t g_ucUART2Buffer[UART2_BUFFER];

//==============================================================================
//              ADC MODULES
//------------------------------------------------------------------------------
void ADCInit(void);

void bsp_adc_software_calibrate(void);
void bsp_adc_get_single_channel_sample_value(uint32_t *conversion_result);
uint32_t bsp_adc_get_channel_voltage(void);

//==============================================================================
//              SPI MODULES
//------------------------------------------------------------------------------

void SPIInit(void);

unsigned char SPISendRece(unsigned char ucOut);

//==============================================================================
//              I2C MODULES
//------------------------------------------------------------------------------

void I2CInit(void);
void error_process(void);
void i2c_delay_time(uint32_t delay_time);

/* I2C延时操作 */

/* I2C返回ACK的类型 */

/* I2C主机读写请求 */

void bsp_i2c_generate_start(void);
void bsp_i2c_generate_stop(void);
void bsp_i2c_generate_ack(uint32_t ack_type);
uint32_t bsp_i2c_master_send_byte(uint8_t data);
uint8_t bsp_i2c_master_receive_byte(void);
void bsp_i2c_master_send(void);
void bsp_i2c_master_receive(void);

//------------------------------------------------------------------------------

//==============================================================================
//              PWM MODULE
//------------------------------------------------------------------------------

void PWMInit(void);

//==============================================================================
//              EXTI MODULE
//------------------------------------------------------------------------------

void EXTIInit(void);

extern uint32_t g_exti_gpio_flag;

/* USER BUTTON GPIO 定义 */
    
/* USER BUTTON EXTI定义*/    

//==============================================================================
//              FLASH WRITE/READ MODULE
//------------------------------------------------------------------------------
void FlashInit(void);

void flash_error_process(void);

/* Flash编程字的个数 */
/* Flash擦写起始页编号:第32页 */
/* Flash擦写起始地址:0x00004000 */

void FlashRead(uint32_t * pBuffer, uint32_t nNumber);
void FlashWrite(uint32_t * pBuffer, uint32_t nNumber);

//==============================================================================
//             END OF FILE : CIU32.H
//------------------------------------------------------------------------------

三、C文件

/*
**==============================================================================
** CIU32.C:             -- by Dr. ZhuoQing, 2025-10-13
**
**==============================================================================
*/

//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
void CIU32F003Init(void) {
    CIU32F003PortInit();
    
    UARTInit();

    UART2Init();

    ADCInit();
    bsp_adc_software_calibrate();

    SPIInit();

    I2CInit();

    PWMInit();
    std_tim_enable(TIM3);

    EXTIInit();

    FlashInit();
    
}

void CIU32F003PortInit(void) {
    
}

//==============================================================================
//                MISCELLANEOUS FUNCTION
//------------------------------------------------------------------------------
void Delay(__IO uint32_t nCount) {
      for(; nCount != 0; nCount--);
}

void WaitTime(uint32_t nTime) {
    std_delayms(nTime);
}

//------------------------------------------------------------------------------
void GPIOSetOutput(uint32_t clkp, GPIO_t * port, uint16_t pin) {
    std_gpio_init_t gpio_config = {0};

    /* 使能LED对应的GPIO时钟 */
    std_rcc_gpio_clk_enable(clkp);

    /* 配置LED的IO */
    gpio_config.pin = pin;
    gpio_config.mode = GPIO_MODE_OUTPUT;
    gpio_config.pull = GPIO_PULLUP;
    gpio_config.output_type = GPIO_OUTPUT_PUSHPULL;
   
    /* 初始化GPIO */
    std_gpio_init(port, &gpio_config);
}

void GPIOSetOutputOD(uint32_t clkp, GPIO_t * port, uint16_t pin) {
    std_gpio_init_t gpio_config = {0};

    /* 使能LED对应的GPIO时钟 */
    std_rcc_gpio_clk_enable(clkp);

    /* 配置LED的IO */
    gpio_config.pin = pin;
    gpio_config.mode = GPIO_MODE_OUTPUT;
    gpio_config.pull = GPIO_NOPULL;
    gpio_config.output_type = GPIO_OUTPUT_OPENDRAIN;
   
    /* 初始化GPIO */
    std_gpio_init(port, &gpio_config);
}

void GPIOSetInput(uint32_t clkp, GPIO_t * port, uint16_t pin) {
    std_gpio_init_t gpio_config = {0};

    /* 使能LED对应的GPIO时钟 */
    std_rcc_gpio_clk_enable(clkp);

    /* 配置LED的IO */
    gpio_config.pin = pin;
    gpio_config.mode = GPIO_MODE_INPUT;
    gpio_config.pull = GPIO_NOPULL;
    gpio_config.output_type = GPIO_OUTPUT_PUSHPULL;
   
    /* 初始化GPIO */
    std_gpio_init(port, &gpio_config);
}

void GPIOSetInputPU(uint32_t clkp, GPIO_t * port, uint16_t pin) {
    std_gpio_init_t gpio_config = {0};

    /* 使能LED对应的GPIO时钟 */
    std_rcc_gpio_clk_enable(clkp);

    /* 配置LED的IO */
    gpio_config.pin = pin;
    gpio_config.mode = GPIO_MODE_INPUT;
    gpio_config.pull = GPIO_PULLUP;
    gpio_config.output_type = GPIO_OUTPUT_PUSHPULL;
   
    /* 初始化GPIO */
    std_gpio_init(port, &gpio_config);
}

void GPIOSetInputPD(uint32_t clkp, GPIO_t * port, uint16_t pin) {
    std_gpio_init_t gpio_config = {0};

    /* 使能LED对应的GPIO时钟 */
    std_rcc_gpio_clk_enable(clkp);

    /* 配置LED的IO */
    gpio_config.pin = pin;
    gpio_config.mode = GPIO_MODE_INPUT;
    gpio_config.pull = GPIO_PULLDOWN;
    gpio_config.output_type = GPIO_OUTPUT_PUSHPULL;
   
    /* 初始化GPIO */
    std_gpio_init(port, &gpio_config);
}

//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
void UARTInit(void) {
    
    std_gpio_init_t gpio_config = {0} ;

    /* 使能UART对应的GPIO时钟 */
    std_rcc_gpio_clk_enable(RCC_PERIPH_CLK_GPIOA);

    /* GPIO引脚配置  
        PA3    ------> TX  
        PA4    ------> RX  
    */
    gpio_config.pin = GPIO_PIN_3|GPIO_PIN_4;
    gpio_config.mode = GPIO_MODE_ALTERNATE;
    gpio_config.pull = GPIO_PULLUP;
    gpio_config.output_type = GPIO_OUTPUT_PUSHPULL;
    gpio_config.alternate = GPIO_AF1_UART1;
    std_gpio_init(GPIOA,&gpio_config);

    std_uart_init_t uart_confg = {0};
    /* UART 时钟使能 */
    std_rcc_apb2_clk_enable(RCC_PERIPH_CLK_UART1);
    
    /* UART 初始化 */
    uart_confg.baudrate = 115200;
    uart_confg.direction = UART_DIRECTION_SEND_RECEIVE;
    uart_confg.wordlength = UART_WORDLENGTH_8BITS;
    uart_confg.stopbits = UART_STOPBITS_1;
    uart_confg.parity = UART_PARITY_NONE;
    std_uart_init(UART1,&uart_confg);
    
    /* 使能UART */
    std_uart_enable(UART1);
    
    g_ucUARTHead = g_ucUARTTail = 0;
    
    NVIC_SetPriority(UART1_IRQn,NVIC_PRIO_1);    
    NVIC_EnableIRQ(UART1_IRQn);
    std_uart_cr1_interrupt_enable(UART1,UART_CR1_INTERRUPT_RXNE);
    
}

//------------------------------------------------------------------------------

/* 定义BUF的长度*/
uint8_t g_ucUARTBuffer[UART_BUFFER];
__IO uint8_t g_ucUARTHead, g_ucUARTTail;
void UART1_IRQHandler(void)
{
     /* 检查上溢错误 */
    if((std_uart_get_cr3_interrupt_err_enable(UART1)                          \
        || std_uart_get_cr1_interrupt_enable(UART1,UART_CR1_INTERRUPT_RXNE))  \
        && std_uart_get_flag(UART1,UART_FLAG_ORE))
    {
        /* 清除上溢错误标志 */
        std_uart_clear_flag(UART1,UART_CLEAR_ORE);
        /* 用户可根据实际使用场景,自定义错误处理流程 */
    }
    
    /* 检查到接收寄存器非空标志后, 读取接收数据 */    
    if(std_uart_get_cr1_interrupt_enable(UART1,UART_CR1_INTERRUPT_RXNE)     \
         && std_uart_get_flag(UART1,UART_FLAG_RXNE)) {
         
         g_ucUARTBuffer[g_ucUARTTail ++] = std_uart_rx_read_data(UART1);
         if(g_ucUARTTail >= UART_BUFFER) {
             g_ucUARTTail = 0;
         }
         
         if(g_ucUARTTail == g_ucUARTHead) {
            if(g_ucUARTTail == 0)  g_ucUARTTail = UART_BUFFER - 1;
            else g_ucUARTTail --;
         }
         
    }
    
    //----------------------------------------------------------------------
            
/*    
    if(std_uart_get_cr1_interrupt_enable(UART1,UART_CR1_INTERRUPT_TXE)        \
         && std_uart_get_flag(UART1,UART_FLAG_TXE))
    {
        std_uart_cr1_interrupt_disable(UART1,UART_CR1_INTERRUPT_TXE);
        std_uart_cr1_interrupt_enable(UART1,UART_CR1_INTERRUPT_TC);
    }

    if(std_uart_get_cr1_interrupt_enable(UART1,UART_CR1_INTERRUPT_TC)         \
        && std_uart_get_flag(UART1,UART_FLAG_TC))
    {
        std_uart_clear_flag(UART1,UART_FLAG_TC);
        std_uart_cr1_interrupt_disable(UART1,UART_CR1_INTERRUPT_TC);
    }
*/
}

//------------------------------------------------------------------------------

unsigned char UARTReceChar(unsigned char *pc) {
    unsigned int i;
    for(i = 0; i < UART_CHECK_LOOP; i ++) {
        if(UART_CANRECE) {
            *(pc) = g_ucUARTBuffer[g_ucUARTHead ++];
            if(g_ucUARTHead >= UART_BUFFER) g_ucUARTHead = 0;
            return 0;
        }
    }
    
    return 1;
}

void UARTSendChar(uint8_t c) {
    uint32_t i;
    
    for(i = 0; i < UART_CHECK_LOOP; i ++) {
        if(std_uart_get_flag(UART1, UART_FLAG_TXE)) {
            std_uart_tx_write_data(UART1, c);
            break;
        }
    }
     
    for(i = 0; i < UART_CHECK_LOOP; i ++) {
        if(std_uart_get_flag(UART1, UART_FLAG_TC)) break;
    }
    
}

unsigned char UARTReceChar(unsigned char *pc) {
    unsigned int i;
    for(i = 0; i < UART_CHECK_LOOP; i ++) {
        if(std_uart_get_flag(UART1, UART_FLAG_RXNE)) {
            *(pc) = std_uart_rx_read_data(UART1);
            return 0;
        }
    }
    
    return 1;
}

void UARTSendChar(uint8_t c) {
    uint32_t i;
    
    for(i = 0; i < UART_CHECK_LOOP; i ++) {
        if(std_uart_get_flag(UART1, UART_FLAG_TXE)) {
            std_uart_tx_write_data(UART1, c);
            break;
        }
    }
     
    for(i = 0; i < UART_CHECK_LOOP; i ++) {
        if(std_uart_get_flag(UART1, UART_FLAG_TC)) break;
    }
    
}

//int putchar(int ch) {
//    UART1SendChar(ch);
//    return ch;
//}

//int fputc(int ch, FILE * f) {
//    UART1SendChar(ch);
//    return ch;
//}

//------------------------------------------------------------------------------
__asm(".global __use_no_semihosting\n\t");
__asm(".global __ARM_use_no_argv \n\t");  
struct __FILE
{
    int handle;
};
int _ttywrch(int ch)
{
    ch = ch;
    return ch;
}
void _sys_exit(int x)
{
    x = x;
}
char *_sys_command_string(char *cmd, int len)
{
    return NULL;
}
FILE __stdout;

int fputc(int ch, FILE *f)
{
    UARTSendChar(ch);
    return ch;
}

//------------------------------------------------------------------------------

int getchar(void) {
    int ch;
    if(UARTReceChar(&ch)) return ch;
    else return 0;
}

//==============================================================================
//                  UART2 MODULE
//------------------------------------------------------------------------------

void UART2Init(void) {
/*    
    std_gpio_init_t gpio_config = {0} ;

    std_rcc_gpio_clk_enable(RCC_PERIPH_CLK_GPIOB);

    gpio_config.pin = GPIO_PIN_2|GPIO_PIN_6;
    gpio_config.mode = GPIO_MODE_ALTERNATE;
    gpio_config.pull = GPIO_PULLUP;
    gpio_config.output_type = GPIO_OUTPUT_PUSHPULL;
    gpio_config.alternate = GPIO_AF5_UART2;
    std_gpio_init(GPIOB,&gpio_config);

    std_uart_init_t uart_confg = {0};
    std_rcc_apb2_clk_enable(RCC_PERIPH_CLK_UART2);
    
    uart_confg.baudrate = 115200;
    uart_confg.direction = UART_DIRECTION_SEND_RECEIVE;
    uart_confg.wordlength = UART_WORDLENGTH_8BITS;
    uart_confg.stopbits = UART_STOPBITS_1;
    uart_confg.parity = UART_PARITY_NONE;
    std_uart_init(UART2,&uart_confg);
    
    std_uart_enable(UART2);
    
    g_ucUART2Head = g_ucUART2Tail = 0;
    
    NVIC_SetPriority(UART2_IRQn,NVIC_PRIO_1);    
    NVIC_EnableIRQ(UART2_IRQn);
    std_uart_cr1_interrupt_enable(UART2,UART_CR1_INTERRUPT_RXNE);
    
*/    
}

//------------------------------------------------------------------------------

uint8_t g_ucUART2Buffer[UART2_BUFFER];
__IO uint8_t g_ucUART2Head, g_ucUART2Tail;

void UART2_IRQHandler(void)
{
     /* 检查上溢错误 */
    if((std_uart_get_cr3_interrupt_err_enable(UART2)                          \
        || std_uart_get_cr1_interrupt_enable(UART2,UART_CR1_INTERRUPT_RXNE))  \
        && std_uart_get_flag(UART2,UART_FLAG_ORE))
    {
        /* 清除上溢错误标志 */
        std_uart_clear_flag(UART2,UART_CLEAR_ORE);
        /* 用户可根据实际使用场景,自定义错误处理流程 */
    }
    
    /* 检查到接收寄存器非空标志后, 读取接收数据 */    
    if(std_uart_get_cr1_interrupt_enable(UART2,UART_CR1_INTERRUPT_RXNE)     \
         && std_uart_get_flag(UART2,UART_FLAG_RXNE)) {
         
         g_ucUART2Buffer[g_ucUART2Tail ++] = std_uart_rx_read_data(UART2);
         if(g_ucUART2Tail >= UART2_BUFFER) {
             g_ucUART2Tail = 0;
         }
         
         if(g_ucUART2Tail == g_ucUART2Head) {
            if(g_ucUART2Tail == 0)  g_ucUART2Tail = UART2_BUFFER - 1;
            else g_ucUART2Tail --;
         }
         
    }
    
    //----------------------------------------------------------------------
            
/*    
    if(std_uart_get_cr1_interrupt_enable(UART1,UART_CR1_INTERRUPT_TXE)        \
         && std_uart_get_flag(UART1,UART_FLAG_TXE))
    {
        std_uart_cr1_interrupt_disable(UART1,UART_CR1_INTERRUPT_TXE);
        std_uart_cr1_interrupt_enable(UART1,UART_CR1_INTERRUPT_TC);
    }

    if(std_uart_get_cr1_interrupt_enable(UART1,UART_CR1_INTERRUPT_TC)         \
        && std_uart_get_flag(UART1,UART_FLAG_TC))
    {
        std_uart_clear_flag(UART1,UART_FLAG_TC);
        std_uart_cr1_interrupt_disable(UART1,UART_CR1_INTERRUPT_TC);
    }
*/
}

//------------------------------------------------------------------------------

unsigned char UART2ReceChar(unsigned char *pc) {
    unsigned int i;
    for(i = 0; i < UART_CHECK_LOOP; i ++) {
        if(UART2_CANRECE) {
            *(pc) = g_ucUART2Buffer[g_ucUART2Head ++];
            if(g_ucUART2Head >= UART2_BUFFER) g_ucUART2Head = 0;
            return 0;
        }
    }
    
    return 1;
}

void UART2SendChar(uint8_t c) {
    uint32_t i;
    
    for(i = 0; i < UART_CHECK_LOOP; i ++) {
        if(std_uart_get_flag(UART2, UART_FLAG_TXE)) {
            std_uart_tx_write_data(UART2, c);
            break;
        }
    }
     
    for(i = 0; i < UART_CHECK_LOOP; i ++) {
        if(std_uart_get_flag(UART2, UART_FLAG_TC)) break;
    }
    
}

unsigned char UART2ReceChar(unsigned char *pc) {
    unsigned int i;
    for(i = 0; i < UART_CHECK_LOOP; i ++) {
        if(std_uart_get_flag(UART2, UART_FLAG_RXNE)) {
            *(pc) = std_uart_rx_read_data(UART2);
            return 0;
        }
    }
    
    return 1;
}

void UART2SendChar(uint8_t c) {
    uint32_t i;
    
    for(i = 0; i < UART_CHECK_LOOP; i ++) {
        if(std_uart_get_flag(UART2, UART_FLAG_TXE)) {
            std_uart_tx_write_data(UART2, c);
            break;
        }
    }
     
    for(i = 0; i < UART_CHECK_LOOP; i ++) {
        if(std_uart_get_flag(UART2, UART_FLAG_TC)) break;
    }
    
}

//==============================================================================
//                      ADC Modules
//------------------------------------------------------------------------------

void ADCInit(void) {
    //--------------------------------------------------------------------------
    /* 使能ADC时钟 */
    std_rcc_apb2_clk_enable(RCC_PERIPH_CLK_ADC);
       
    /* ADC_CK时钟为PCLK的3分频 */
    std_adc_clock_config(ADC_CK_DIV3);
    
    /* 软件触发ADC */
    std_adc_trig_sw();

    /* 单次转换模式 */
    std_adc_conversion_mode_config(ADC_SINGLE_CONVER_MODE);
    
    /* 采样时间配置,119个周期*/
    std_adc_sampt_time_config(ADC_SAMPTIME_119CYCLES);
     
    /* 选择通道4 */
    std_adc_fix_sequence_channel_enable(ADC_CHANNEL);
    
    /* 配置wait模式,避免数据未及时读取,转换溢出 */
    std_adc_wait_mode_enable();

    /* 使能ADC */
    std_adc_enable();
    
    /* 等待ADC使能状态稳定 */
    std_delayus(ADC_EN_DELAY);
    std_gpio_init_t adc_gpio_config = {0};

    //--------------------------------------------------------------------------
    /* 使能GPIOA时钟 */
    std_rcc_gpio_clk_enable(RCC_PERIPH_CLK_GPIOA);
    
    /* ADC_IN4输入通道配置:PA7 */
    adc_gpio_config.pin = ADC_PIN;
    adc_gpio_config.mode = GPIO_MODE_ANALOG;
    adc_gpio_config.pull = GPIO_NOPULL;
    std_gpio_init(GPIOA, &adc_gpio_config);
    
}

/*--------------------------------------------define--------------------------------------------*/
/* ADC参考电压为VDDA:3300mV。在实际应用中需根据真实的VDD电压值设置该值 */

/* ADC采样次数,根据实际需求可调整此值 */

/* 校准系数的最值 */

/* ADC校准系数的符号位 */

/* ADC补偿值 */

/*------------------------------------------functions-------------------------------------------*/
/**
* @brief  提升ADC校准系数的精度
* @retval 无
*/
void bsp_adc_software_calibrate(void)
{
    int32_t get_calfact = 0;
    
    /* 使能校准 */
    std_adc_calibration_enable();
    
    /* 等待校准完成 */
    while(std_adc_get_flag(ADC_FLAG_EOCAL) == 0U);
    
    /* 清除ADC转换状态,确保之前状态不影响转换 */
    std_adc_clear_flag(ADC_FLAG_ALL);
    
    get_calfact = std_adc_get_calibration_factor();
    
    /* 判断校准系数符号位 */
    if(get_calfact & ADC_CALFACT_SYMBOL)
    {
        /* 校准系数是负值,转换成32位有符号负数,方便计算 */
        get_calfact = get_calfact | 0xFFFFFFE0;
    }
    
    /* 校准系数减去ADC补偿值获取新的校准系数 */
    get_calfact = get_calfact - ADC_COMPENSATION_VALUE;
    
    /* 判断校准系数是否超限 */
    if(get_calfact > CALFACT_MAX)
    {
        get_calfact = CALFACT_MAX;
    }
    else if(get_calfact < CALFACT_MIN)
    {
        get_calfact = CALFACT_MIN;
    }
    std_adc_calibration_factor_config(get_calfact);
}

/**
* @brief  获取转换通道采样值
* @param  conversion_result 通道采样值
* @retval 无
*/
void bsp_adc_get_single_channel_sample_value(uint32_t *conversion_result)
{
    /* 启动转换 */
    std_adc_start_conversion();
    /* 等待channel转换完成 */
    while(std_adc_get_flag(ADC_FLAG_EOC) == 0U);

    /* 清除EOC标志 */
    std_adc_clear_flag(ADC_FLAG_EOC);
        
    /* 获取通道采样值 */
    *conversion_result = std_adc_get_conversion_value();
}

/**
* @brief  转换ADC通道采样值为实际电压值
* @retval uint32_t 转换结果
*/
uint32_t bsp_adc_get_channel_voltage(void)
{
    uint32_t get_sample_sum = 0;
    uint32_t get_channel_voltage = 0;
    uint32_t get_single_sample = 0;
    
    /* ADC多次采样取平均,提升采样精度 */
    for(uint8_t i = 0; i < ADC_SAMPLE_NUM; i++)
    {
        bsp_adc_get_single_channel_sample_value(&get_single_sample);
        get_sample_sum += get_single_sample;
    }
    
    /* 计算平均值 */
    get_single_sample = get_sample_sum / ADC_SAMPLE_NUM;
    
    /* 计算采样通道电压 */
    get_channel_voltage = get_single_sample * VREF_ADC_VDDA_VOLTAGE / ADC_CONVER_SCALE;

    return get_channel_voltage;
}

//==============================================================================
//              SPI MODULES
//------------------------------------------------------------------------------

void SPIInit(void) {
    std_gpio_init_t gpio_config = {0};
    
    /* GPIO外设时钟使能 */  
    std_rcc_gpio_clk_enable(RCC_PERIPH_CLK_GPIOA | RCC_PERIPH_CLK_GPIOB);
    /* SPI1 GPIO 配置    
        PB1     ------> SPI1_NSS
        PB0     ------> SPI1_SCK
        PA1     ------> SPI1_MISO
        PA0     ------> SPI1_MOSI
    */
    gpio_config.pin = GPIO_PIN_0 | GPIO_PIN_1;
    gpio_config.mode = GPIO_MODE_ALTERNATE;
    gpio_config.pull = GPIO_NOPULL;
    gpio_config.output_type = GPIO_OUTPUT_PUSHPULL;
    gpio_config.alternate = GPIO_AF0_SPI1;
    std_gpio_init(GPIOA, &gpio_config);

    gpio_config.pin = GPIO_PIN_0 | GPIO_PIN_1;
    gpio_config.pull = GPIO_PULLUP;
    std_gpio_init(GPIOB, &gpio_config);

    //--------------------------------------------------------------------------
    std_spi_init_t spi_config = {0};
    
    /* SPI1时钟使能 */
    std_rcc_apb2_clk_enable(RCC_PERIPH_CLK_SPI1);
    
    /* 禁止SPI */
    std_spi_disable();
    
    /* SPI结构体初始化 */
    spi_config.mode = SPI_MODE_MASTER;
    spi_config.baud_rate_prescaler = SPI_BAUD_PCLKDIV_32;
    spi_config.clk_polarity = SPI_POLARITY_HIGH;
    spi_config.clk_phase = SPI_PHASE_1EDGE;
    spi_config.bitorder = SPI_FIRSTBIT_MSB;
    std_spi_init(&spi_config);
    
    /* SPI主机模式,配置NSS输出使能 */
    std_spi_nss_output_enable();
    
    /* SPI使能 */
    std_spi_enable();
    
}

unsigned char SPISendRece(unsigned char ucOut) {
    
    /* 等待发送数据寄存器为空 */
    while(std_spi_get_flag(SPI_FLAG_TXFE) != SPI_FLAG_TXFE);
    /* 发送数据 */
    std_spi_write_data(ucOut);
    
    /* 等待接收数据寄存器非空 */
    while(std_spi_get_flag(SPI_FLAG_RXFNE) != SPI_FLAG_RXFNE);
    /* 接收数据 */ 
    unsigned char ucRet;
    ucRet = std_spi_read_data();

    /* SPI主机拉高片选信号,结束通信 */
    while(!std_spi_get_flag(SPI_FLAG_TXFE));
    while(std_spi_get_flag(SPI_FLAG_BUSY));
    
    return ucRet;
}

//==============================================================================
//              I2C MODULES
//------------------------------------------------------------------------------

void I2CInit(void) {
    std_gpio_init_t gpio_config = {0};
    
    /* 使能I2C GPIO时钟 */
    std_rcc_gpio_clk_enable(RCC_PERIPH_CLK_GPIOB);
    
    /* 设置SCL SDA默认输出高电平 */
    std_gpio_set_pin(I2C_PIN_PORT, (SCL_PIN | SDA_PIN));
    
    /* 初始化I2C GPIO */
    gpio_config.pin = (SCL_PIN | SDA_PIN);
    gpio_config.mode = GPIO_MODE_OUTPUT;
    gpio_config.output_type = GPIO_OUTPUT_OPENDRAIN;
    gpio_config.pull = GPIO_NOPULL;
    std_gpio_init(I2C_PIN_PORT, &gpio_config);
}

/**
* @brief  异常处理
* @retval 无
*/
void error_process(void)
{
    /* 用户添加异常处理流程 */
    
    while(1)
    {
    }
}

/**
* @brief  I2C延时函数
* @param  delay_time 延时计数值
* @note   用户可更改延时计数值来调整I2C的通信速率
* @retval 无
*/
void i2c_delay_time(uint32_t delay_time)
{
    uint32_t delay_cnt;
    
    for(delay_cnt=delay_time; delay_cnt>0; delay_cnt--);
}

/*------------------------------------------define----------------------------------------------*/   
/*------------------------------------------variables-------------------------------------------*/
uint8_t g_tx_buffer[BUFF_SIZE] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
uint8_t g_rx_buffer[BUFF_SIZE];

/*------------------------------------------functions-------------------------------------------*/
/**
* @brief  I2C生成起始位
* @retval 无
*/
void bsp_i2c_generate_start(void)
{
    /* 切换输出模式前固定电平状态以避免毛刺 */
    std_gpio_set_pin(I2C_PIN_PORT, (SCL_PIN | SDA_PIN));
    /* 设置SDA为输出模式 */
    std_gpio_set_pin_mode(I2C_PIN_PORT, SDA_PIN, GPIO_MODE_OUTPUT);
    i2c_delay_time(CLK_DELAY);
    std_gpio_reset_pin(I2C_PIN_PORT, SDA_PIN);
    i2c_delay_time(CLK_DELAY);
    std_gpio_reset_pin(I2C_PIN_PORT, SCL_PIN);
}

/**
* @brief  I2C生成停止位
* @retval 无
*/
void bsp_i2c_generate_stop(void)
{
    /* 切换输出模式前固定电平状态以避免毛刺 */
    std_gpio_reset_pin(I2C_PIN_PORT, (SCL_PIN | SDA_PIN));
    /* 设置SDA为输出模式 */
    std_gpio_set_pin_mode(I2C_PIN_PORT, SDA_PIN, GPIO_MODE_OUTPUT);
    i2c_delay_time(CLK_DELAY);
    std_gpio_set_pin(I2C_PIN_PORT, SCL_PIN);
    i2c_delay_time(CLK_DELAY);
    std_gpio_set_pin(I2C_PIN_PORT, SDA_PIN);
}

/**
* @brief  I2C生成ACK/NACK
* @param  ack_type ACK类型
*             @arg RET_ACK:  主机发送ACK
*             @arg RET_NACK: 主机发送NACK
* @retval 无
*/
void bsp_i2c_generate_ack(uint32_t ack_type)
{
    /* 切换输出模式前根据返回ACK/NACK固定电平状态以避免毛刺 */
    if(ack_type == RET_ACK)
    {
        std_gpio_reset_pin(I2C_PIN_PORT, SDA_PIN);
    }
    else
    {
        std_gpio_set_pin(I2C_PIN_PORT, SDA_PIN);
    }
    
    /* 设置SDA为输出模式 */
    std_gpio_set_pin_mode(I2C_PIN_PORT, SDA_PIN, GPIO_MODE_OUTPUT);
    
    i2c_delay_time(CLK_DELAY);
    std_gpio_set_pin(I2C_PIN_PORT, SCL_PIN);
    i2c_delay_time(CLK_DELAY);
    std_gpio_reset_pin(I2C_PIN_PORT, SCL_PIN);
}

/**
* @brief  I2C主模式发送一个字节数据
* @param  data 发送数据
* @retval uint32_t 返回从机ACK状态
*             @arg RET_ACK:  从机返回ACK
*             @arg RET_NACK: 从机返回NACK
*/
uint32_t bsp_i2c_master_send_byte(uint8_t send_data)
{
    uint32_t bit_cnt = 0;
    uint32_t ack_type = 0;
    
    /* 切换输出模式前固定电平状态以避免毛刺 */
    if (send_data & 0x80)
    {
        std_gpio_set_pin(I2C_PIN_PORT, SDA_PIN);
    }
    else
    {
        std_gpio_reset_pin(I2C_PIN_PORT, SDA_PIN);
    }
    
    /* 设置SDA为输出模式 */
    std_gpio_set_pin_mode(I2C_PIN_PORT, SDA_PIN, GPIO_MODE_OUTPUT);
    
    /* 发送8bit数据 */
    for (bit_cnt=0; bit_cnt < 8; bit_cnt++)
    {
        if ((send_data << bit_cnt) & 0x80)
        {
            std_gpio_set_pin(I2C_PIN_PORT, SDA_PIN);
        }
        else
        {
            std_gpio_reset_pin(I2C_PIN_PORT, SDA_PIN);
        }
        i2c_delay_time(CLK_DELAY);
        std_gpio_set_pin(I2C_PIN_PORT, SCL_PIN);
        i2c_delay_time(CLK_DELAY);
        std_gpio_reset_pin(I2C_PIN_PORT, SCL_PIN);
    }
    
    /* 判断从机返回ACK */
    std_gpio_set_pin_mode(I2C_PIN_PORT, SDA_PIN, GPIO_MODE_INPUT);
    i2c_delay_time(CLK_DELAY);
    std_gpio_set_pin(I2C_PIN_PORT, SCL_PIN);
    i2c_delay_time(ACK_DELAY);
    
    for (bit_cnt=0; bit_cnt < 5; bit_cnt++)
    {
        if (std_gpio_get_input_pin(I2C_PIN_PORT, SDA_PIN) == false)
        {
            ack_type = RET_ACK;
        }
        else
        {
            ack_type = RET_NACK;
            break;
        }
    }
    std_gpio_reset_pin(I2C_PIN_PORT, SCL_PIN);
    i2c_delay_time(CLK_DELAY);
    
    return ack_type;
}

/**
* @brief  I2C主模式接收一个字节数据
* @retval uint8_t 接收数据
*/
uint8_t bsp_i2c_master_receive_byte(void)
{
    uint32_t bit_cnt = 0;
    uint8_t receive_data = 0;
    
    /* 设置SDA为输入状态 */
    std_gpio_set_pin_mode(I2C_PIN_PORT, SDA_PIN, GPIO_MODE_INPUT);
    
    /* 接收8bit数据 */
    for (bit_cnt=0; bit_cnt<8; bit_cnt++)
    {
        std_gpio_reset_pin(I2C_PIN_PORT, SCL_PIN);
        i2c_delay_time(CLK_DELAY);
        std_gpio_set_pin(I2C_PIN_PORT, SCL_PIN);
        i2c_delay_time(CLK_DELAY);
        
        receive_data = receive_data << 1;
        if (std_gpio_get_input_pin(I2C_PIN_PORT, SDA_PIN) == true)
        {
            receive_data += 1;
        }
    }
    std_gpio_reset_pin(I2C_PIN_PORT, SCL_PIN);
    i2c_delay_time(CLK_DELAY);
    
    return receive_data;
}

/**
* @brief  I2C主模式发送数据流程
* @retval 无
*/
void bsp_i2c_master_send(void)
{
    uint32_t ack_type;
    uint32_t index;
    
    /* 发送start位 */
    bsp_i2c_generate_start();
    
    /* 发送从机地址及写请求 */
    ack_type = bsp_i2c_master_send_byte(SLAVE_ADDRESS | REQ_WRITE);
    if (ack_type != RET_ACK)
    {
        error_process();
    }
    
    /* 地址匹配转数据发送延时 */
    /* 用户可根据实际从机地址匹配后的时序进行调整 */
    i2c_delay_time(USER_DELAY);
    
    /* 发送数据 */
    for (index=0; index<BUFF_SIZE; index++)
    {
        ack_type = bsp_i2c_master_send_byte(g_tx_buffer[index]);
        if (ack_type != RET_ACK)
        {
            error_process();
        }
    }
    
    /* 发送stop位 */
    bsp_i2c_generate_stop();
}

/**
* @brief  I2C主模式接收数据
* @retval 无
*/
void bsp_i2c_master_receive(void)
{
    uint32_t ack_type;
    uint32_t index;
    
    /* 发送start位 */
    bsp_i2c_generate_start();
    
    /* 发送从机地址及读请求 */
    ack_type = bsp_i2c_master_send_byte(SLAVE_ADDRESS | REQ_READ);
    if (ack_type != RET_ACK)
    {
        error_process();
    }
    
    /* 地址匹配转数据接收延时 */
    /* 用户可根据实际从机地址匹配后的时序进行调整 */
    i2c_delay_time(USER_DELAY);
    
    /* 接收数据 */
    for (index=0; index<BUFF_SIZE-1; index++)
    {
        g_rx_buffer[index] = bsp_i2c_master_receive_byte();
        bsp_i2c_generate_ack(RET_ACK);
    }
    g_rx_buffer[index] = bsp_i2c_master_receive_byte();
    bsp_i2c_generate_ack(RET_NACK);
    
    /* 发送stop位 */
    bsp_i2c_generate_stop();
}

//==============================================================================
//              PWM MODULE
//------------------------------------------------------------------------------

void PWMInit(void) {
    std_gpio_init_t tim3_gpio_init = {0};
    
    /* GPIO时钟使能 */
    std_rcc_gpio_clk_enable(RCC_PERIPH_CLK_GPIOA);
    
    /* TIM3 GPIO 配置
    PA5     ------> TIM3_CH1
    PA4     ------> TIM3_CH2  */
    tim3_gpio_init.pin = GPIO_PIN_5; //GPIO_PIN_4 | GPIO_PIN_5;
    tim3_gpio_init.mode = GPIO_MODE_ALTERNATE;
    tim3_gpio_init.pull = GPIO_NOPULL;
    tim3_gpio_init.alternate = GPIO_AF3_TIM3;
    std_gpio_init(GPIOA, &tim3_gpio_init);    

    std_tim_basic_init_t basic_init_struct = {0};
    std_tim_output_compare_init_t oc_config_struct = {0};
    
    /* TIM3时钟使能 */
    std_rcc_apb1_clk_enable(RCC_PERIPH_CLK_TIM3);
    
    /* 配置TIM3计数器参数 */
    basic_init_struct.prescaler = TIM_PRESCALER_VALUE;
    basic_init_struct.period = TIM_PERIOD_VALUE;
    basic_init_struct.clock_div = TIM_CLOCK_DTS_DIV1;
    std_tim_init(TIM3, &basic_init_struct);
        
    /* 配置通道1输出模式为PWM1模式 */
    oc_config_struct.output_compare_mode = TIM_OUTPUT_MODE_PWM1;
    oc_config_struct.output_pol = TIM_OUTPUT_POL_HIGH;
    oc_config_struct.pulse = TIM_PULSE1_VALUE;
    oc_config_struct.output_state = TIM_OUTPUT_ENABLE;
    std_tim_output_compare_init(TIM3, &oc_config_struct, TIM_CHANNEL_1);
    
    /* 配置通道2输出模式为PWM1模式 */
    oc_config_struct.pulse = TIM_PULSE2_VALUE;
    std_tim_output_compare_init(TIM3, &oc_config_struct, TIM_CHANNEL_2);
}

//==============================================================================
//              EXTI MODULE
//------------------------------------------------------------------------------

void EXTIInit(void) {
    g_exti_gpio_flag = 0;

    std_gpio_init_t gpio_config = {0} ;

    /* 使能LED对应的GPIO时钟 */
    std_rcc_gpio_clk_enable(RCC_PERIPH_CLK_GPIOB);

    /* 配置USER BUTTON 的IO*/
    gpio_config.pin = USER_BUTTON_PIN;
    gpio_config.mode = GPIO_MODE_INPUT;
    gpio_config.pull = GPIO_NOPULL;
    
    /* 初始化 USER Button 的GPIO */
    std_gpio_init(USER_BUTTON_GPIO_PORT, &gpio_config);
    
    std_exti_init_t exti_config = {0} ;
      
    /* 配置USER Button的EXTI */
    exti_config.line_id = USER_BUTTON_EXTI_LINE;
    exti_config.mode = EXTI_MODE_INTERRUPT;
    exti_config.trigger = EXTI_TRIGGER_FALLING;
    exti_config.gpio_id = USER_BUTTON_EXTI_PORT;
    /* 初始化EXTI*/
    std_exti_init(&exti_config);

    /* 配置中断优先级 */
    NVIC_SetPriority(EXTI2_3_IRQn, NVIC_PRIO_3); 
    /* 使能中断 */
    NVIC_EnableIRQ(EXTI2_3_IRQn);
}

/*------------------------------------------variables-------------------------------------------*/
uint32_t g_exti_gpio_flag;

/*------------------------------------------functions-------------------------------------------*/
/**
* @brief  EXTI2_3中断服务函数
* @retval 无
*/
void EXTI2_3_IRQHandler(void)
{
    /* 读取EXTI通道中断挂起状态 */
    if (std_exti_get_pending_status(USER_BUTTON_EXTI_LINE))
    {
        /* 清除EXTI通道中断挂起状态 */
        std_exti_clear_pending(USER_BUTTON_EXTI_LINE);
        g_exti_gpio_flag = 1;
    }
}

//==============================================================================
//              FLASH WRITE/READ MODULE
//------------------------------------------------------------------------------
void FlashInit(void) {
    
}

//------------------------------------------------------------------------------

void FlashRead(uint32_t * pBuffer, uint32_t nNumber) {

    uint32_t i;
    for(i = 0; i < nNumber; i ++) {
        uint32_t * p = (uint32_t *)(FLASH_ERASE_PROGRAM_ADDR + (i << 2));
        *(pBuffer + i) = *(p);
    }
}

//------------------------------------------------------------------------------
void FlashWrite(uint32_t * pBuffer, uint32_t nNumber) {

    /* 清除所有标志位 */
    std_flash_clear_flag(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR);

    /* Flash控制寄存器解锁 */
    std_flash_unlock();
    
    /* Flash擦除 */
    if (STD_OK != std_flash_erase(FLASH_MODE_PAGE_ERASE, FLASH_ERASE_PROGRAM_ADDR))
    {
        flash_error_process();
    }
     
    uint32_t word_count;
    /* Flash编程 */
    for (word_count = 0; word_count < nNumber; word_count++)
    {
        uint32_t program_data = *(pBuffer + word_count);
        
        if (STD_OK != std_flash_word_program((FLASH_ERASE_PROGRAM_ADDR + (word_count << 2)), program_data))
        {
            flash_error_process();
        }
        
        /* 校验编程数据 */
        if (*(uint32_t *)(FLASH_ERASE_PROGRAM_ADDR + (word_count << 2)) != program_data)
        {
            /* 校验异常,加入自定义处理代码 */
            flash_error_process();
        }
    }
        
    /* Flash控制寄存器加锁 */
    std_flash_lock();
}

void flash_error_process(void)
{
    /* 用户可以在此处加入异常处理代码 */
    
    while(1)
    {
    }
}

//==============================================================================
//                END OF FILE : CIU32.C
//------------------------------------------------------------------------------


Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐