富芮坤FR800X使用笔记

800X资料下载:

1.SDK下载:FR8000: 富芮坤低功耗蓝牙软件开发包(BLE SDK)适用于该公司出品的FR800x系列低功耗蓝牙SOC芯片。如有任何问题请联系sales@freqchip.com咨询。

用户手册和specification位于SDK/docs目录,请务必查阅

2.资料下载:硬件产品-企业官网

系统时钟的配置:

system_set_clock(SYSTEM_CLOCK_SEL);//

注意:SYSTEM_CLOCK_SEL及一些关键定义在app_config.h内,如log配置,连接数量设置等

系统堆栈配置:

查看proj_main.c文件下的宏定义

#define SYSTEM_STACK_SIZE           0x800

LDO电压(引脚电压)配置:

将PMU_ALDO_3_3V修改到对应电压即可

void pmu_sub_init(void)
{
    .......
       ool_write(PMU_REG_IOLDO_CFG_2, ((ool_read(PMU_REG_IOLDO_CFG_2)&0xf8)|PMU_ALDO_3_3V));          // set IOLDO output voltage, flash Mode Pin down
    ool_write(PMU_REG_IOLDO_CFG_3, ((ool_read(PMU_REG_IOLDO_CFG_3)&0x1F)|(PMU_ALDO_3_3V << 5)));   // set IOLDO output voltage, flash Mode Pin up
    .......
}

IOLDO BYPASS模式开启和关闭:

__attribute__((section("ram_code"))) void pmu_ioldo_bypass(bool on)
{  
    if(on) {
        ool_write(PMU_REG_IOLDO_CFG_1, ool_read(PMU_REG_IOLDO_CFG_1) | 0x20);
    }
    else {
        ool_write(PMU_REG_IOLDO_CFG_1, ool_read(PMU_REG_IOLDO_CFG_1) & ~0x20);
    }
}

IOLDO_SW开启关闭方式:

 pmu_ioldosw_ctrl(true);
 pmu_ioldosw_ctrl(false);

GPIO的使用:

__SYSTEM_GPIO_CLK_ENABLE();//开总线
//初始化 E0
GPIO_InitTypeDef GPIO_Handle;
// Output 
GPIO_Handle.Pin       = GPIO_PIN_0;
GPIO_Handle.Mode      = GPIO_MODE_OUTPUT_PP;
gpio_init(GPIO_E, &GPIO_Handle);
//函数设置输出
gpio_write_pin(GPIO_E, GPIO_PIN_0, GPIO_PIN_SET);
gpio_write_pin(GPIO_E, TEST_GPIO_PIN, GPIO_PIN_CLEAR);
//直接操作寄存器输出
GPIO->PortE_DATA = GPIO->PortE_DATA | GPIO_PIN_0;
GPIO->PortE_DATA = GPIO->PortE_DATA & ~GPIO_PIN_0;
//函数读取
gpio_read_pin(GPIO_E, GPIO_PIN_0);
gpio_read_pin(TEST_GPIO, TEST_GPIO_PIN);
//寄存器读取
uint8_t value = GPIO->PortA_DATA&GPIO_PIN_0

RTC的使用:

rtc_init();
rtc_CountUpdate(0);
rtc_AlarmConfig(AlARM_A,0,0,1);
NVIC_EnableIRQ(PMU_IRQn);	

设置后每秒钟会触发pmu_isr中断一次,在中断中判断具体哪个中断

__attribute__((section("ram_code"))) void pmu_isr(void)
{
    uint16_t state = pmu_get_isr_state();
 
    //co_printf("pmu_isr: %04x.\r\n", state);
    if(state & PMU_CALI_INT_STATUS) {
        /* restart calibration */
        pmu_get_rc_clk(true);
		pmu_calibration_stop();
//        pmu_calibration_restart(LP_RC_CALIB_LARGE_CNT);
       // LOG_INFO(NULL, "lp clock is %d.\r\n", pmu_get_rc_clk(false));
    }
	
    if(state & PMU_GPIO_XOR_INT_STATUS) {
		uint32_t pin_value= ool_read32(PMU_REG_PORTA_LAST_STATUS);
		uint8_t pin_value_e = ool_read(PMU_REG_PORTE_LAST_STATUS);//
		//LOG_DBG(NULL, "pmu gpio value is %08x.\r\n", pin_value);
		pmu_gpio_isr(pin_value);
		ool_write32(PMU_REG_PORTA_LAST_STATUS, pin_value);
		ool_write(PMU_REG_PORTE_LAST_STATUS, pin_value_e);
    }
        rtc_AlarmHandler(state);
	pmu_clear_isr_state(state);
}
__attribute__((section("ram_code"))) void rtc_AlarmHandler(uint16_t state)
{
    if (state & PMU_RTC_ALMA_INT_STATUS) 
    {
		 co_printf("rtc_AlarmHandler\r\n");
        pmu_clear_isr_state(PMU_RTC_ALMA_INT_CLR);

        /* Alarm cycle */
        AlarmTime_A.CycleBackup += AlarmTime_A.FirstBackup;

        rtc_AlarmConfig(AlARM_A, 0, 0, AlarmTime_A.CycleBackup);
    }
    else if (state & PMU_RTC_ALMB_INT_STATUS) 
    {
        pmu_clear_isr_state(PMU_RTC_ALMB_INT_CLR);

        /* Alarm cycle */
        AlarmTime_B.CycleBackup += AlarmTime_B.FirstBackup;

        rtc_AlarmConfig(AlARM_B, 0, 0, AlarmTime_B.CycleBackup);
    }
}

PMU中断的配置:

pmu_port_wakeup_func_set(GPIO_PORT_A, (1<<GPIO_BIT_2));
NVIC_EnableIRQ(PMU_IRQn);
//中断入口
__attribute__((weak)) void pmu_gpio_isr(uint32_t pin_value)
{
}

串口及中断的配置方式:
 

void uart_isr_int(UART_HandleTypeDef *huart)
{
    huart->UARTx->IER_DLH.IER.ELSI = 1;
    huart->UARTx->IER_DLH.IER.ERBFI = 1;
}

void uart0_init(void)
{
  __SYSTEM_UART0_CLK_SELECT_96M();
    __SYSTEM_UART0_CLK_ENABLE();

    system_set_port_pull(GPIO_PA0,GPIO_PULL_UP,true);
    system_set_port_mux(GPIO_PORT_A, GPIO_BIT_0, PORTA0_FUNC_UART0_RXD);
    system_set_port_mux(GPIO_PORT_A, GPIO_BIT_1, PORTA1_FUNC_UART0_TXD);    __SYSTEM_UART0_CLK_ENABLE();
    
    Uart0_handle.UARTx = Uart0;
    Uart0_handle.Init.BaudRate   = 9600;
    Uart0_handle.Init.DataLength = UART_DATA_LENGTH_8BIT;
    Uart0_handle.Init.StopBits   = UART_STOPBITS_1 ;
    Uart0_handle.Init.Parity     = UART_PARITY_NONE;
    Uart0_handle.Init.FIFO_Mode  = UART_FIFO_ENABLE;
    uart_init_ex(&Uart0_handle);
    NVIC_SetPriority(UART0_IRQn, 1);
    NVIC_EnableIRQ(UART0_IRQn);
    /*enable recv and line status interrupt*/
    uart_isr_int(&Uart0_handle);
 uint8_t buf[4] = {'1', '2', '3', '4'};            
    uart_transmit(&Uart0_handle, buf2, 4);
}


void uart1_init(void)
{
        __SYSTEM_UART1_CLK_ENABLE();
        system_set_port_pull(GPIO_PD6,GPIO_PULL_UP,true);
    
    /* set PA2 and PA3 for AT command interface */
    system_set_port_mux(GPIO_PORT_D, GPIO_BIT_6, PORTD6_FUNC_UART1_RXD);
    system_set_port_mux(GPIO_PORT_D, GPIO_BIT_7, PORTD7_FUNC_UART1_TXD);
    
    Uart1_handle.UARTx = Uart1;
    Uart1_handle.Init.BaudRate   = 9600;
    Uart1_handle.Init.DataLength = UART_DATA_LENGTH_8BIT;
    Uart1_handle.Init.StopBits   = UART_STOPBITS_1 ;
    Uart1_handle.Init.Parity     = UART_PARITY_NONE;
    Uart1_handle.Init.FIFO_Mode  = UART_FIFO_ENABLE;

    uart_init_ex(&Uart1_handle);
    
    NVIC_EnableIRQ(UART1_IRQn);
    NVIC_SetPriority(UART1_IRQn, 0);
    /*enable recv and line status interrupt*/
    uart_isr_int(&Uart1_handle);
uint8_t buf[4] = {'1', '2', '3', '4'};
 uart_transmit(&Uart1_handle, buf, 4);    
}


__attribute__((section("ram_code"))) void uart0_isr(void)
{
    uint32_t isr_id;
    volatile struct_UART_t * const uart_reg_ram = (volatile struct_UART_t *)UART0_BASE;
    isr_id = uart_reg_ram->FCR_IID.IID;
    if(((isr_id & 0x04) == 0x04) || ((isr_id & 0x0c) == 0x0c)) //receciver data available or character timeout indication
    {
        while(uart_reg_ram->LSR.LSR_BIT.DR)
        {
            uint8_t data = (uint8_t)uart_reg_ram->DATA_DLL.DATA;
            //co_printf("uart0:%02x\r\n",data);
            uart_putc_noint_no_wait(UART0, data);
        }
    }
    else if((isr_id & 0x06) == 0x06)//receiver line status interrupt
    {
        uint32_t tmp = uart_reg_ram->LSR.LSR_DWORD;
        uart_reg_ram->FCR_IID.FCR = isr_id;
        uart_reg_ram->IER_DLH.IER.ELSI = 0;
    }
}

__attribute__((section("ram_code"))) void uart1_isr(void)
{
    uint32_t isr_id;
    volatile struct_UART_t * const uart_reg_ram = (volatile struct_UART_t *)UART1_BASE;
    isr_id = uart_reg_ram->FCR_IID.IID;
    if(((isr_id & 0x04) == 0x04) || ((isr_id & 0x0c) == 0x0c)) //receciver data available or character timeout indication
    {
        while(uart_reg_ram->LSR.LSR_BIT.DR)
        {
#if 1            
            uint8_t data = (uint8_t)uart_reg_ram->DATA_DLL.DATA;
            //co_printf("uart1:%02x\r\n",data);
            uart_putc_noint_no_wait(UART1, data);
#else // err            
            timer_start(Timer0);
            dma_start(&DMA_Chan1, (uint32_t)&uart_reg_ram->DATA_DLL.DATA, (uint32_t)RxBuffer8, 32, DMA_BURST_LEN_32, DMA_BURST_LEN_32);
#endif            
        }
    }
    else if((isr_id & 0x06) == 0x06)//receiver line status interrupt
    {
        uint32_t tmp = uart_reg_ram->LSR.LSR_DWORD;
        uart_reg_ram->FCR_IID.FCR = isr_id;
        uart_reg_ram->IER_DLH.IER.ELSI = 0;
    }
}

ADC的使用:

//测试代码使用了IO口 D4 - D7,对应ADC通道channel3-channel0

D4 ----- ADC_CHANNEL_3

D5 ----- ADC_CHANNEL_2

D6 ----- ADC_CHANNEL_1

D7 ----- ADC_CHANNEL_0

使用下面函数会对使用 FT 测试参数校准 ADC 结果

uint32_t adc_get_data_FT(void)

//init config gpio
  system_set_port_mux(GPIO_PORT_D, GPIO_BIT_4, PORTD4_FUNC_SARADC4);
  system_set_port_mux(GPIO_PORT_D, GPIO_BIT_5, PORTD5_FUNC_SARADC5);
  system_set_port_mux(GPIO_PORT_D, GPIO_BIT_6, PORTD6_FUNC_SARADC6);
  system_set_port_mux(GPIO_PORT_D, GPIO_BIT_7, PORTD7_FUNC_SARADC7);    
  __SYSTEM_ADC_CLK_ENABLE();
  
//example 1  单通道/多通道转换,不使用FIFO
        adc_InitParameter_t ADC_InitParam;
        ADC_InitParam.ADC_CLK_DIV          = 5;
        ADC_InitParam.ADC_SetupDelay       = 80;
        ADC_InitParam.ADC_Reference        = ADC_REF_LDOIO;
        ADC_InitParam.FIFO_Enable          = FIFO_DISABLE;
        ADC_InitParam.FIFO_AlmostFullLevel = 0;
        adc_init(ADC_InitParam);
        adc_Channel_ConvertConfig(ADC_CHANNEL_0|ADC_CHANNEL_1|ADC_CHANNEL_2|ADC_CHANNEL_3);
        adc_convert_enable();        
      
        for (i = 0; i < 4; i++)
        {
           co_printf("Channel[%d] = %d \r\n", i, adc_get_channel_data(i));
        }
    }
//example 2  单通道/多通道转换,使用FIFO
        adc_InitParameter_t ADC_InitParam;        
        uint16_t DataBuffer[200];
        uint32_t Count = 0;
                
        ADC_InitParam.ADC_CLK_DIV          = 5;
        ADC_InitParam.ADC_SetupDelay       = 80;
        ADC_InitParam.ADC_Reference        = ADC_REF_LDOIO;
        ADC_InitParam.FIFO_Enable          = FIFO_ENABLE;
        ADC_InitParam.FIFO_AlmostFullLevel = 8;
        adc_init(ADC_InitParam);        
        adc_Channel_ConvertConfig(ADC_CHANNEL_0|ADC_CHANNEL_1|ADC_CHANNEL_2|ADC_CHANNEL_3);
        adc_convert_enable();        
        while (1) 
        {
            while(!(adc_get_fifo_Status() & FIFO_ALMOST_FULL));            
            for (i = 0; i < 8; i++)
            {
                DataBuffer[Count++] = adc_get_data();
            }            
            if (Count > 100) 
            {
                adc_convert_disable();                
                for (i = 0; i < 100; i++)
                {
                    co_printf("Channel[%d] = %d \r\n", i % 4, DataBuffer[i]);
                }            
                Count = 0;                
                adc_convert_enable();
            }
           //提示:在这里采用一段时间再打印是因为,如果启用了FIFO,
           //边采样边打印导致来不及从FIFO取出数据,FIFO就直接溢出了,溢出后将导致FIFO错误
        }
    }
//example 3  单通道/多通道转换,使用FIFO,使用DMA
        DMA_HandleTypeDef  DMA_Chan0;
        uint16_t Buffer2[256];
        adc_InitParameter_t ADC_InitParam;           
        
        ADC_InitParam.ADC_CLK_DIV          = 5;
        ADC_InitParam.ADC_SetupDelay       = 80;
        ADC_InitParam.ADC_Reference        = ADC_REF_1P2V;
        ADC_InitParam.FIFO_Enable          = FIFO_ENABLE;
        ADC_InitParam.FIFO_AlmostFullLevel = 32;
        ADC_InitParam.DMA_Enable           = DMA_ENABLE;
        ADC_InitParam.DMA_Level            = 60;
        adc_init(ADC_InitParam);
        adc_Channel_ConvertConfig(ADC_CHANNEL_0);  
         __SYSTEM_DMA_CLK_ENABLE();// 开dma总线     
         __DMA_REQ_ID_ADC(3);//DMA请求号
        
        DMA_Chan0.Channel = DMA_Channel0;
        DMA_Chan0.Init.Data_Flow        = DMA_P2M_DMAC;
        DMA_Chan0.Init.Request_ID       = 3;
        DMA_Chan0.Init.Source_Inc       = DMA_ADDR_INC_NO_CHANGE;
        DMA_Chan0.Init.Desination_Inc   = DMA_ADDR_INC_INC;
        DMA_Chan0.Init.Source_Width     = DMA_TRANSFER_WIDTH_16;
        DMA_Chan0.Init.Desination_Width = DMA_TRANSFER_WIDTH_16;
        dma_init(&DMA_Chan0);
        dma_start(&DMA_Chan0, (uint32_t)0x50090024, (uint32_t)Buffer2, 60, DMA_BURST_LEN_1, DMA_BURST_LEN_1);
        adc_convert_enable();
        while(!dma_get_tfr_Status(DMA_Channel0));        
        dma_clear_tfr_Status(DMA_Channel0);        
        for (i = 0; i < 60; i++)
        {
            co_printf("%d \r\n", Buffer2[i]);
        }
    }

 //example 3  采集VBAT电压,不使用FIFO,采集到的为1/4 VBAT    
     adc_InitParameter_t ADC_InitParam;         
     ADC_InitParam.ADC_CLK_DIV          = 5;
     ADC_InitParam.ADC_SetupDelay       = 80;
     ADC_InitParam.ADC_Reference        = ADC_REF_LDOIO;
     ADC_InitParam.FIFO_Enable          = FIFO_DISABLE;
     ADC_InitParam.FIFO_AlmostFullLevel = 0;
     adc_init(ADC_InitParam);
     adc_VBAT_ConvertConfig();
     adc_convert_enable();        

     while(1)
     {
        if (adc_DataValid_status() == true) 
        {
             co_printf("VBE = %d \r\n", adc_get_data());
        }
    }  
//example 4  采集VBE核心温度,不使用FIFO
        adc_InitParameter_t ADC_InitParam;        
        ADC_InitParam.ADC_CLK_DIV          = 5;
        ADC_InitParam.ADC_SetupDelay       = 80;
        ADC_InitParam.ADC_Reference        = ADC_REF_LDOIO;
        ADC_InitParam.FIFO_Enable          = FIFO_DISABLE;
        ADC_InitParam.FIFO_AlmostFullLevel = 0;
        adc_init(ADC_InitParam);
        adc_VBE_ConvertConfig();
        adc_convert_enable();        
        while(1)
        {
            if (adc_DataValid_status() == true) 
            {
                co_printf("VBE = %d \r\n", adc_get_data());
            }
        }

USB的配置:

如果使用专用USB口的话直接使用例程就可以,如果使用gpio复用为USB,需要注意一下几个方面。

1.将usb pad配置为false

pmu_usb_pad_ctrl(false);

2.在usb_device_init函数内修改一下使用gpio复用为usb

*(volatile uint32_t *)0x5000003C = 0x000C5F09;//0x000C4F09:usb phy   0x000C5F09:gpio

3.如下为usb cdc初始化代码

void usb_demo(void)
{
	__SYSTEM_UART1_CLK_ENABLE();
	system_set_port_pull(GPIO_PC2|GPIO_PC3, GPIO_PULL_UP, true);
	system_set_port_mux(GPIO_PORT_C, GPIO_BIT_2, PORTC2_FUNC_UART1_RXD);
	system_set_port_mux(GPIO_PORT_C, GPIO_BIT_3, PORTC3_FUNC_UART1_TXD);
	system_regs->rst.uart1_rst = 0;
  uart_init(UART1, LOG_UART_BAUDRATE_CFG);
//	uart_write(UART1, "HELLO\r\n",7);
	
	NVIC_ClearPendingIRQ(USBMCU_IRQn);
	NVIC_SetPriority(USBMCU_IRQn, 0);
	NVIC_EnableIRQ(USBMCU_IRQn);
	system_set_port_mux(GPIO_PORT_A, GPIO_BIT_0, PORTA0_FUNC_USB_DP);
	system_set_port_mux(GPIO_PORT_A, GPIO_BIT_1, PORTA1_FUNC_USB_DM);
	usb_device_init();
	usb_cdc_init();
	
	usb_DP_Pullup_Enable();

	while(1)
	{
		usb_cdc_serialReceive();
	}
}

内置LCD接口的使用:

参考jd9854驱动配置代码部分:SDK\components\driver\ components\display\driver_jd9854.c

或者:有道云笔记

SPI四线模式+DMA操作flash参考:

有道云笔记

iic 主机的使用:

    __SYSTEM_GPIO_CLK_ENABLE();
    __SYSTEM_I2C0_CLK_ENABLE();
	
	/* I2C IO Init */
    GPIO_Handle.Pin       = GPIO_PIN_0 | GPIO_PIN_1;
    GPIO_Handle.Mode      = GPIO_MODE_AF_PP;
    GPIO_Handle.Pull      = GPIO_PULLUP;
    GPIO_Handle.Alternate = GPIO_FUNCTION_1;
    gpio_init(GPIO_D, &GPIO_Handle);

	/* I2C Init */
    I2C0_Handle.I2Cx = I2C0;
    I2C0_Handle.Init.I2C_Mode = I2C_MODE_MASTER_7BIT;
    I2C0_Handle.Init.SCL_HCNT = 60;
    I2C0_Handle.Init.SCL_LCNT = 60;
    i2c_init(&I2C0_Handle);

uint8_t I2C_Write(uint8_t slave_address,uint8_t cmd_reg,uint8_t data)
{
	uint8_t buff[2];
	buff[0] = cmd_reg;
	buff[1] = data;
	i2c_master_transmit(&I2C0_Handle,slave_address,buff,2);
	return 	true;
}
uint8_t I2C_Read(uint8_t slave_address,uint8_t cmd_reg,uint8_t *state_commu)
{
	uint8_t buff = 0;
	i2c_master_transmit(&I2C0_Handle,slave_address,&cmd_reg,1);
	i2c_master_receive(&I2C0_Handle,slave_address,&buff,1);
	*state_commu = true;
	return 	buff;
}

iic 从机的使用

#include "driver_gpio.h"
#include "driver_i2c.h"

//使用i2c需要外部上拉

#define MASTER    0 //主从机切换

static GPIO_InitTypeDef   GPIO_Handle;
static I2C_HandleTypeDef  I2C0_Handle;

static uint8_t data[2]={0};
static uint8_t i2c_slave_RxBufferI2C[256]={0};


uint8_t TxBufferI2C[256];
uint8_t RxBufferI2C[256];

static uint32_t recv_count = 0;
static uint32_t send_count = 0;


void user_i2c_app_init(void)
{
      __SYSTEM_GPIO_CLK_ENABLE();
      __SYSTEM_I2C0_CLK_ENABLE();
    
      /* I2C IO Init */
    GPIO_Handle.Pin       = GPIO_PIN_0 | GPIO_PIN_1;
    GPIO_Handle.Mode      = GPIO_MODE_AF_PP;
    GPIO_Handle.Pull      = GPIO_PULLUP;
    GPIO_Handle.Alternate = GPIO_FUNCTION_1;
    gpio_init(GPIO_D, &GPIO_Handle);
        

    I2C0_Handle.I2Cx = I2C0;
      #if MASTER
    I2C0_Handle.Init.I2C_Mode = I2C_MODE_MASTER_7BIT;
      printf("MASTER Init\r\n");
        #else
        printf("SLAVE Init\r\n");
      I2C0_Handle.Init.I2C_Mode = I2C_MODE_SLAVE_7BIT;
      I2C0_Handle.Init.Slave_Address = (0x5c << 1); //7位地址 左移1位写入 实际发送api会自动处理地址
        #endif
    I2C0_Handle.Init.SCL_HCNT = 50;
    I2C0_Handle.Init.SCL_LCNT = 50;
    i2c_init(&I2C0_Handle);
        
        
        #if  !MASTER
        i2c_IRQHandler(&I2C0_Handle);
        i2c_int_enable(&I2C0_Handle, INT_RX_FULL|INT_RD_REQ|INT_RX_UNDER|INT_RX_OVER|INT_RX_DONE);
    NVIC_EnableIRQ(I2C0_IRQn);
    co_delay_100us(1000);
    __I2C_ENABLE(I2C0_Handle.I2Cx);
        #endif
    
    #if  MASTER
    while(1)
    {
        
        #if 1
      i2c_master_Write(0xA7,0x45,0x67);
        #else
    i2c_master_Read(0xA7,0x37,data,1);
        printf("data=%d\r\n",data[0]);
        #endif
        
    }
    #else
    
    while(1)
    {
    
      //printf("data=%d\r\n",data[0]);
    }
    
    
    #endif
    


}



uint8_t i2c_master_Write(uint8_t slave_address,uint8_t cmd_reg,uint8_t data)
{
    uint8_t buff[2];
    buff[0] = cmd_reg;
    buff[1] = data;
    i2c_master_transmit(&I2C0_Handle,slave_address,buff,2);
    return  true;
}
uint8_t i2c_master_Read(uint8_t slave_address,uint8_t cmd_reg,uint8_t *data,uint8_t len)
{
    i2c_master_transmit(&I2C0_Handle,slave_address,&cmd_reg,1);
    i2c_master_receive(&I2C0_Handle,slave_address,data,len);
    
    return  true;
}

//注意中断入口函数要和boot_vectors.s里的入口函数名称相同
__attribute__((section("ram_code"))) void i2c0_isr(void)
{
    printf("i2c_isr0\r\n");
//    LOG_INFO(NULL, "i2c0_isr: %04x\r\n", I2C0_Handle.I2Cx->RAW_INT_STAT);
    
    if(i2c_get_int_status(&I2C0_Handle, INT_RD_REQ)) {
        if(i2c_get_int_status(&I2C0_Handle, INT_TX_ABRT)) {
            i2c_clear_int_status(&I2C0_Handle, INT_TX_ABRT);
        }
        I2C0_Handle.I2Cx->DATA_CMD = i2c_slave_RxBufferI2C[send_count++];
        i2c_clear_int_status(&I2C0_Handle, INT_RD_REQ);
    }
    
//    if(i2c_get_int_status(&I2C0_Handle, INT_ACTIVITY)) {
//        i2c_clear_int_status(&I2C0_Handle, INT_ACTIVITY);
//    }
//    
//    if(i2c_get_int_status(&I2C0_Handle, INT_STOP_DET)) {
//        i2c_clear_int_status(&I2C0_Handle, INT_STOP_DET);
//    }
//    
//    if(i2c_get_int_status(&I2C0_Handle, INT_START_DET)) {
//        i2c_clear_int_status(&I2C0_Handle, INT_START_DET);
//    }
    
    if(i2c_get_int_status(&I2C0_Handle, INT_RX_FULL)) {
        i2c_clear_int_status(&I2C0_Handle, INT_RX_FULL);
        
        while (!__I2C_IS_RxFIFO_EMPTY(I2C0_Handle.I2Cx)) 
        {
            volatile uint8_t data = I2C0_Handle.I2Cx->DATA_CMD & 0xFF;
            i2c_slave_RxBufferI2C[(recv_count++)%255] = data;            

            printf("i2c_demo: I2C0 receive: %02x.\r\n", data);
        }
    }
}

IWDG的使用:

	wdt_Init_t wdt;
	uint32_t second_timer = 5;//5秒超时复位
	 co_printf("lp clock is %d %d.\r\n", pmu_get_rc_clk(false));
	wdt.WdtCount = second_timer*pmu_get_rc_clk(false);
	wdt.Timeout = 1;
	wdt.IRQ_Enable = WDT_IRQ_ENABLE;
    	wdt_init(wdt);
	while(1)
	{
		wdt_Refresh();
		co_delay_100us(1000*10);
	}

硬件TIMER的使用:

两路硬件定时器,32bit 定时器,向下计数

#define TIMER_CNT_US(us) ((us)*system_get_clock_config())

__SYSTEM_TIMER_CLK_ENABLE();

timer_init(Timer0, TIMER_CNT_US(1000*1000), 0);//1s
timer_start(Timer0);
NVIC_SetPriority(TIMER0_IRQn, 2);
NVIC_EnableIRQ(TIMER0_IRQn);
__attribute__((section("ram_code"))) void timer0_handler(void)
{
	timer_int_clear(Timer0);
	co_printf("Timer0\r\n");		
}

软件OS TIMER的使用:

//头文件 os_timer.h
os_timer_t test_timer;
void timer_test_callback(void *parm)
{
	LOG_INFO(app_tag, "os timer doing\r\n");
}

初始化并开始软件定时器即可,软件定时器最小10ms

os_timer_init(&test_timer,timer_test_callback,NULL);
os_timer_start(&test_timer,1000,true);//1s

PSRAM的初始化:

供电:8008xP型号才有psram

pmu_ioldosw_ctrl(true);
uint8_t *img_buff = (uint8_t *)0x22000000;
void user_psram_init(void)
{
	uint32_t psram_id = 0;
	co_printf("psram init\r\n");
	system_set_port_mux(GPIO_PORT_C, GPIO_BIT_0, PORTC0_FUNC_QSPI0_IO3);
   system_set_port_mux(GPIO_PORT_C, GPIO_BIT_1, PORTC1_FUNC_QSPI0_SCLK0);
   system_set_port_mux(GPIO_PORT_C, GPIO_BIT_2, PORTC2_FUNC_QSPI0_CSN0);
   system_set_port_mux(GPIO_PORT_C, GPIO_BIT_3, PORTC3_FUNC_QSPI0_IO1);
   system_set_port_mux(GPIO_PORT_C, GPIO_BIT_4, PORTC4_FUNC_QSPI0_IO2);
   system_set_port_mux(GPIO_PORT_C, GPIO_BIT_5, PORTC5_FUNC_QSPI0_IO0);
   psram_init();
   //测试psram 是否正常
	img_buff[0] = 1;
	if(img_buff[0] == 1)
	co_printf("psram is ok\r\n");
	else 
	co_printf("psram is fail\r\n");
}

唯一ID做MAC地址:

 uint8_t id[6]={0};
 mac_addr_t mac_addr;
    system_get_unique_ID(id);
 if((id[0]==0)&&(id[1]==0)&&(id[2]==0)&&(id[3]==0)&&(id[4]==0)&&(id[5]==0))
 {
     mac_addr_t mac_addr;
  mac_addr.addr[0] = 0x20;
  mac_addr.addr[1] = 0x33;
  mac_addr.addr[2] = 0x22;
  mac_addr.addr[3] = 0x28;
  mac_addr.addr[4] = 0x22;
  mac_addr.addr[5] = 0xC2;
 }else{
  memcpy(mac_addr.addr,id,6);
 }
 gap_address_set(&mac_addr, BLE_ADDR_TYPE_PRIVATE);
 

获取系统剩余的RAM数量:

//返回值为字节
co_printf("os_get_free_heap_size %d\r\n",os_get_free_heap_size());

配置系统flash工作在qspi(忽略,不可用):

 system_regs->mdm_qspi_cfg.qspi_ref_128m_en = 1; // configure qspi reference clock to 128MHz
 system_regs->mdm_qspi_cfg.qspi_ref_clk_sel = 2; // qspi is used for internal flash, set its reference clock to 96MHz
 system_enable_internal_flash_q_read();
 system_set_internal_flash_clock_div(0);

DMA memcopy封装,有助于提升psram拷贝速度

/*
 * INCLUDE FILES
 ****************************************************************************************
 */
#include <stdio.h>
#include <string.h>

#include "IC_W25Qxx.h"
#include "driver_dma.h"

DMA_HandleTypeDef 	MEM_COPY_DMA_Handle;

void memcopy_dma_init(void)
{
	__SYSTEM_DMA_CLK_ENABLE();
		
	//ÅäÖÃdma
    MEM_COPY_DMA_Handle.Channel               = DMA_Channel0;
    MEM_COPY_DMA_Handle.Init.Data_Flow        = DMA_M2M_DMAC;
    MEM_COPY_DMA_Handle.Init.Request_ID       = 0;
    MEM_COPY_DMA_Handle.Init.Source_Inc       = DMA_ADDR_INC_INC;
    MEM_COPY_DMA_Handle.Init.Desination_Inc   = DMA_ADDR_INC_INC;
    MEM_COPY_DMA_Handle.Init.Source_Width     = DMA_TRANSFER_WIDTH_32;
    MEM_COPY_DMA_Handle.Init.Desination_Width = DMA_TRANSFER_WIDTH_32;
    dma_init(&MEM_COPY_DMA_Handle);
}

void memcopy_dma(uint8_t *dst,uint8_t *src,uint32_t len)
{
    	uint16_t count = len/2048;
    	uint16_t last_len = len%2048;
    	for(uint16_t i = 0; i < count; i++)
    	{
    		uint32_t offset = 2048*i;
    		dma_start(&MEM_COPY_DMA_Handle, (uint32_t)&src[offset],(uint32_t)&dst[offset], 2048/4, DMA_BURST_LEN_16,DMA_BURST_LEN_16);
    		while(!dma_get_tfr_Status(DMA_Channel0));
    		dma_clear_tfr_Status(DMA_Channel0);
    	}
    	if(last_len)
    	{
    		uint32_t offset = len-last_len;
    		dma_start(&MEM_COPY_DMA_Handle, (uint32_t)&src[offset],(uint32_t)&dst[offset], last_len, DMA_BURST_LEN_16,DMA_BURST_LEN_16);
    		while(!dma_get_tfr_Status(DMA_Channel0));
    		dma_clear_tfr_Status(DMA_Channel0);
    	}
}

  • 7
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
富芮坤fr8016ha是一款自带计数的跳绳,跳绳的计数、暂停、复位等功能都可以通过按键进行控制。以下是基于Arduino平台的参考代码: #include <LiquidCrystal_I2C.h> //LCD库 #define BUTTON_COUNT 4 //按键数量 #define BUTTON_PIN 2 //按键引脚 #define LED_PIN 13 //LED引脚 #define LED_ON_DURATION 100 //LED亮时长(ms) #define LCD_WIDTH 16 //LCD宽度(字符) #define LCD_HEIGHT 2 //LCD高度(行数) LiquidCrystal_I2C lcd(0x27, LCD_WIDTH, LCD_HEIGHT); //创建LCD对象 int buttonPins[BUTTON_COUNT] = {2, 3, 4, 5}; //按键引脚列表 int buttonStates[BUTTON_COUNT] = {HIGH, HIGH, HIGH, HIGH}; //按键状态列表 int lastButtonStates[BUTTON_COUNT] = {HIGH, HIGH, HIGH, HIGH}; //上次按键状态列表 int buttonClicked[BUTTON_COUNT] = {0, 0, 0, 0}; //按键单击状态列表 int ledState = LOW; //LED当前状态 unsigned long ledOnTime = 0; //LED亮起时间 int jumpCount = 0; //跳绳计数 bool jumpPaused = false; //跳绳暂停状态 void setup() { pinMode(LED_PIN, OUTPUT); //设置LED引脚为输出 lcd.init(); //初始化LCD lcd.backlight(); //打开背光 lcd.setCursor(0, 0); //设置光标位置 lcd.print("Jump Count: 0"); //显示初始计数 } void loop() { //读取按键状态 for (int i = 0; i < BUTTON_COUNT; i++) { lastButtonStates[i] = buttonStates[i]; buttonStates[i] = digitalRead(buttonPins[i]); if (buttonStates[i] == LOW && lastButtonStates[i] == HIGH) { buttonClicked[i] = 1; } else { buttonClicked[i] = 0; } } //按键单击处理 if (buttonClicked[0]) { //计数 jumpCount++; if (jumpPaused) { jumpPaused = false; } displayJumpCount(); flashLed(); } if (buttonClicked[1]) { //暂停/恢复 jumpPaused = !jumpPaused; displayJumpCount(); flashLed(); } if (buttonClicked[2]) { //复位 jumpCount = 0; jumpPaused = false; displayJumpCount(); flashLed(); } if (buttonClicked[3]) { //测试 testButton(); } //LED计时控制 if (ledState == HIGH && millis() - ledOnTime >= LED_ON_DURATION) { ledState = LOW; digitalWrite(LED_PIN, ledState); } //跳绳暂停判断 if (jumpPaused) { while (digitalRead(buttonPins[1]) == LOW) { //等待恢复按键 delay(50); } } delay(50); } void displayJumpCount() { lcd.setCursor(0, 0); //设置光标位置 lcd.print("Jump Count: "); //显示计数标题 lcd.print(jumpCount); //显示实际计数值 lcd.setCursor(0, 1); //设置光标位置 if (jumpPaused) { lcd.print("Jump Paused"); } else { lcd.print(" "); //清空暂停提示文本 } } void flashLed() { ledState = HIGH; digitalWrite(LED_PIN, ledState); ledOnTime = millis(); } void testButton() { for (int i = 0; i < BUTTON_COUNT; i++) { lcd.setCursor(0, i); lcd.print("\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"); while (digitalRead(buttonPins[i]) != LOW) { delay(50); } lcd.setCursor(0, i); lcd.print(buttonPins[i]); delay(1000); } } 代码中定义了4个按键分别对应计数、暂停/恢复、复位、测试操作。其中测试操作是为了调试按键,非正式的功能。 跳绳计数直接在计数按键响应中进行,每次计数时显示计数值并闪烁LED。跳绳暂停和恢复则在暂停/恢复按键响应中进行,切换暂停状态并显示相应的文本。跳绳复位则在复位按键响应中进行,将计数清零并恢复计数。另外需要注意的是,跳绳暂停时如果用户一直按住暂停/恢复按键则应该在恢复前等待用户松开按键。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值