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)
注意:若需要低功耗,使用完ADC记得调用pmu_adc_power_control(false);关闭ADC电源,避免漏电
//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);
}
}