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