学习一款MCU,首先习惯学习它的外设,这里XR806的外设有一些Demo是在device\xradio\xr806\xr_skylark\project\example目录下的,但是直接编译这个目录下的例程,是会有问题的,
但目前没有解决,所以,就把相应的例程移植到led的例程中可以编译成功.
先上代码.
main的代码如下:
#include <stdio.h>
#include "ohos_init.h"
#include "kernel/os/os.h"
#include "iot_gpio.h"
#include "kernel/os/os_timer.h"
#include "driver/chip/hal_timer.h"
#include "driver/chip/hal_i2c.h"
static OS_Thread_t g_main_thread;
#define GPIO_ID_PA21 21
#define TIMERID TIMER0_ID
#define HFCLOCK 24000000
#define CLK_PRESCALER 4
#define COUNT_TIME 1
uint32_t sec_count;
#define IIC_ID I2C0_ID
#define IIC_FREQ 200000
#define IIC_AT24C16_ADDR 0x50
#define IIC_AT24C16_PAGE_SIZE (16)
OS_Timer_t os_timer;
uint32_t os_sec_count=0;
void os_timer_callback(void *arg)
{
os_sec_count++;
printf("os timer irq: %d\n\r", (int)os_sec_count);
IoTGpioSetOutputVal(12, os_sec_count%2);
}
void os_timer_test(void)
{
OS_Status status = OS_OK;
status = OS_TimerCreate(&os_timer, OS_TIMER_PERIODIC, os_timer_callback, NULL, 1000);
printf("os timer int error %d\n", status);
status = OS_TimerStart(&os_timer);
printf("os timer int error %d\n", status);
}
#if 1
void timer_callback(void *arg)
{
sec_count++;
printf(" timer irq: %d\n\r", sec_count);
IoTGpioSetOutputVal(11, sec_count%2);
}
int timer_init(void)
{
HAL_Status status = HAL_ERROR;
TIMER_InitParam param;
param.arg = NULL;
param.callback = timer_callback;
param.cfg = HAL_TIMER_MakeInitCfg(TIMER_MODE_REPEAT,
TIMER_CLK_SRC_HFCLK,
TIMER_CLK_PRESCALER_4);
param.isEnableIRQ = 1;
param.period = COUNT_TIME * (HFCLOCK / CLK_PRESCALER);
status = HAL_TIMER_Init(TIMERID, ¶m);
if (status != HAL_OK)
printf("timer int error %d\n", status);
return status;
}
int timer_deinit(void)
{
HAL_Status status = HAL_ERROR;
status = HAL_TIMER_DeInit(TIMERID);
if (status != HAL_OK)
printf("timer deinit error %d\n", status);
return status;
}
#endif
static void MainThread(void *arg)
{
printf("LED test start\r\n");
IoTGpioInit(GPIO_ID_PA21);
IoTGpioSetDir(GPIO_ID_PA21, IOT_GPIO_DIR_OUT);
IoTGpioInit(11);
IoTGpioSetDir(11, IOT_GPIO_DIR_OUT);
IoTGpioInit(12);
IoTGpioSetDir(12, IOT_GPIO_DIR_OUT);
timer_init();
HAL_TIMER_Start(TIMERID);
os_timer_test();
while (1)
{
IoTGpioSetOutputVal(21, 1);
OS_MSleep(500);
IoTGpioSetOutputVal(21, 0);
OS_MSleep(500);
}
}
void LEDMain(void)
{
printf("LED Test Start\n");
if (OS_ThreadCreate(&g_main_thread, "MainThread", MainThread, NULL,
OS_THREAD_PRIO_APP, 4 * 1024) != OS_OK)
{
printf("[ERR] Create MainThread Failed\n");
}
}
SYS_RUN(LEDMain);
这个程序烧到板子上,发现两个定时器的时间不一样,串口输出如下 .
![image.png image.png](//file.elecfans.com/web2/M00/7B/60/poYBAGN1qsSAfUWOAABl9s1HI0s773.jpg)
这就很奇怪了,例程中都是定时1s,于是都翻转个IO口进行测试.
波形如下,可以看到os定时器的时间是对的,硬件定时器的时间小于1S
![IMG_20211229_170813.jpg IMG_20211229_170813.jpg](//file.elecfans.com/web2/M00/7B/EE/pYYBAGN1qsmACEJpABW_meBXwlo233.jpg)
![IMG_20211229_170738.jpg IMG_20211229_170738.jpg](//file.elecfans.com/web2/M00/7B/60/poYBAGN1qsmAIEpjABZs2ArBY8k381.jpg)
于是在程序开始的地方,注意到
#define HFCLOCK 24000000
但XR806的晶振是40M才对.所以,修改后
#define HFCLOCK 40000000
定时器时间才对上了.
![image.png image.png](//file.elecfans.com/web2/M00/7B/EE/pYYBAGN1qsSAWJEcAABBabv1inA977.jpg)
不知道这个是例程的bug,还是这个例程原来是针对的是其他的板子的.
疑问
目前这个芯片折腾了有一段时间了,感觉整个的SDK的架构不是很明晰,在例程中直接使用鸿蒙的系统中的一些函数,却无法使用,如鸿蒙OS的定时器使用的是OsSwtmrTaskCreate,但在SDK中使用的是OS_TimerCreate,这个源码是在:
xr806_openharmony/device/xradio/xr806/xr_skylark/src/kernel/os/FreeRTOS
这看上去是FreeRTOS的内核中的函数,而不是鸿蒙的.而且看源码中的前面的注释,也真不是鸿蒙的.
真正的鸿蒙的内核源码应该是在:
/xr806_openharmony/kernel/liteos_m/kernel/src
但在这个目录下,并没有发现 .d与 .o的文件,说明这里的文件是没有编译的.
所以.这里所说的支持鸿蒙,到底是支持的哪些,有一些搞不懂了.
原作者:ifconfig