1 /*
2  * Copyright (c) 2022-2024, Xiaohua Semiconductor Co., Ltd.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2024-12-30     CDT          first version
9  */
10 
11 /*
12  * 程序清单:这是一个 I2C 设备使用例程
13  * 例程导出了 pcf8563 命令到控制终端
14  * 命令调用格式:i2c_pcf8563_sample i2c1
15  * 命令解释:命令第二个参数是要使用的I2C总线设备名称,为空则使用默认的I2C总线设备
16  * 程序功能:通过 I2C 设备读取时间信息并打印
17 */
18 
19 #include <rtthread.h>
20 #include <rtdevice.h>
21 
22 #if defined(BSP_USING_I2C)
23 
24 #define PFC8563_I2C_BUS_NAME            "i2c1"  /* I2C总线设备名称 */
25 #define PFC8563_ADDR                    0x51    /* 从机地址 */
26 #define PFC8563_REG_SEC                 0x02    /* 校准命令 */
27 #define PFC8563_REG_CTRL_SR1            0x00    /* 校准命令 */
28 
29 #define PFC8563_TIME_LEN                0x7    /* 获取数据长度 */
30 
31 
32 #define RTC_DEC2BCD(__DATA__)           ((((__DATA__) / 10U) << 4U) + ((__DATA__) % 10U))
33 #define RTC_BCD2DEC(__DATA__)           ((((__DATA__) >> 4U) * 10U) + ((__DATA__) & 0x0FU))
34 
35 
36 static struct rt_i2c_bus_device *i2c_bus = RT_NULL;     /* I2C总线设备句柄 */
37 static rt_bool_t initialized = RT_FALSE;                /* 传感器初始化状态 */
38 
39 /* 写传感器寄存器 */
write_regs(struct rt_i2c_bus_device * bus,rt_uint8_t reg,rt_uint8_t * data,rt_uint8_t len)40 static rt_err_t write_regs(struct rt_i2c_bus_device *bus, rt_uint8_t reg, rt_uint8_t *data, rt_uint8_t len)
41 {
42     rt_uint8_t buf[16 + 1];
43     struct rt_i2c_msg msgs;
44     rt_uint32_t buf_size = 1;
45 
46     buf[0] = reg;   // cmd
47     if (data != RT_NULL)
48     {
49         memcpy(&buf[1], data, len);
50         buf_size += len;
51     }
52 
53     msgs.addr = PFC8563_ADDR;
54     msgs.flags = RT_I2C_WR;
55     msgs.buf = buf;
56     msgs.len = buf_size;
57 
58     /* 调用I2C设备接口传输数据 */
59     if (rt_i2c_transfer(bus, &msgs, 1) == 1)
60     {
61         return RT_EOK;
62     }
63     else
64     {
65         rt_kprintf("write regs failed!\n");
66         return -RT_ERROR;
67     }
68 }
69 
70 /* 读传感器寄存器数据 */
read_regs(struct rt_i2c_bus_device * bus,rt_uint8_t reg,rt_uint8_t * data,rt_uint8_t len)71 static rt_err_t read_regs(struct rt_i2c_bus_device *bus, rt_uint8_t reg, rt_uint8_t *data, rt_uint8_t len)
72 {
73     struct rt_i2c_msg msgs[2];
74     rt_uint8_t buf[16 + 1];
75     rt_uint32_t buf_size = 1;
76 
77     buf[0] = reg;   // cmd
78     msgs[0].addr = PFC8563_ADDR;
79     msgs[0].flags = RT_I2C_WR;
80     msgs[0].buf = buf;
81     msgs[0].len = buf_size;
82 
83     msgs[1].addr = PFC8563_ADDR;
84     msgs[1].flags = RT_I2C_RD;
85     msgs[1].buf = data;
86     msgs[1].len = len;
87 
88     /* 调用I2C设备接口传输数据 */
89     if (rt_i2c_transfer(bus, &msgs[0], 2) == 2)
90     {
91         return RT_EOK;
92     }
93     else
94     {
95         rt_kprintf("read regs failed!\n");
96         return -RT_ERROR;
97     }
98 }
99 
pcf8563_init(const char * name)100 static void pcf8563_init(const char *name)
101 {
102     rt_uint8_t temp[16];
103 
104     /* 查找I2C总线设备,获取I2C总线设备句柄 */
105     i2c_bus = (struct rt_i2c_bus_device *)rt_device_find(name);
106 
107     if (i2c_bus == RT_NULL)
108     {
109         rt_kprintf("can't find %s device!\n", name);
110     }
111     else
112     {
113         rt_thread_mdelay(500);
114         temp[0] = 0x28U;
115         write_regs(i2c_bus, PFC8563_REG_CTRL_SR1, temp, 1);
116         rt_thread_mdelay(100);
117         temp[0] = 0x08U;
118         write_regs(i2c_bus, PFC8563_REG_CTRL_SR1, temp, 1);
119         rt_thread_mdelay(100);
120 
121         temp[0] = RTC_DEC2BCD(55);
122         temp[1] = RTC_DEC2BCD(59);
123         temp[2] = RTC_DEC2BCD(23);
124         temp[3] = RTC_DEC2BCD(1);
125         temp[4] = RTC_DEC2BCD(3);
126         temp[5] = RTC_DEC2BCD(1);
127         temp[6] = RTC_DEC2BCD(20);
128         write_regs(i2c_bus, PFC8563_REG_SEC, temp, PFC8563_TIME_LEN);
129         rt_thread_mdelay(100);
130         initialized = RT_TRUE;
131     }
132 }
133 
serial_thread_entry(void * parameter)134 static void serial_thread_entry(void *parameter)
135 {
136     rt_uint8_t time[16];
137 
138     memset(time, 0, 16);
139     rt_thread_mdelay(500);
140     rt_thread_mdelay(500);
141 
142     while (1)
143     {
144         // if (RT_EOK == read_regs(i2c_bus, PFC8563_REG_SEC, time, PFC8563_TIME_LEN))
145         if (RT_EOK == read_regs(i2c_bus, PFC8563_REG_SEC, time, 1))
146         {
147             time[0] &= 0x7FU;
148             time[1] &= 0x7FU;
149             time[2] &= 0x3FU;
150             time[3] &= 0x3FU;
151             time[4] &= 0x7U;
152             time[5] &= 0x1FU;
153             time[6] &= 0xFFU;
154             /* Print current date and time */
155             rt_kprintf("Time: 20%02d/%02d/%02d %02d:%02d:%02d\n", RTC_BCD2DEC(time[6]), RTC_BCD2DEC(time[5]),
156                        RTC_BCD2DEC(time[3]), RTC_BCD2DEC(time[2]), RTC_BCD2DEC(time[1]), RTC_BCD2DEC(time[0]));
157         }
158         else
159         {
160             rt_kprintf("Get time failed!\n");
161         }
162         rt_thread_mdelay(100);
163     }
164 }
165 
i2c_pcf8563_sample(int argc,char * argv[])166 void i2c_pcf8563_sample(int argc, char *argv[])
167 {
168     char bus_name[RT_NAME_MAX];
169 
170     if (argc == 2)
171     {
172         rt_strncpy(bus_name, argv[1], RT_NAME_MAX);
173     }
174     else
175     {
176         rt_strncpy(bus_name, PFC8563_I2C_BUS_NAME, RT_NAME_MAX);
177     }
178 
179     if (!initialized)
180     {
181         /* 传感器初始化 */
182         pcf8563_init(bus_name);
183     }
184     if (initialized)
185     {
186         /* 创建 serial 线程 */
187         rt_thread_t thread = rt_thread_create("serial", serial_thread_entry, RT_NULL, 1024, 25, 10);
188         /* 创建成功则启动线程 */
189         if (thread != RT_NULL)
190         {
191             rt_thread_startup(thread);
192         }
193         else
194         {
195             rt_kprintf("startup thread failed!\n");
196         }
197     }
198     else
199     {
200         rt_kprintf("initialize sensor failed!\n");
201     }
202 }
203 /* 导出到 msh 命令列表中 */
204 MSH_CMD_EXPORT(i2c_pcf8563_sample, i2c aht10 sample);
205 
206 #endif
207