串口是单片机最常用的外设之一。本次创建面向对象来移植UART 的驱动。
本文引用地址:
1 学习例程
百问网的面向对象的这UART驱动,源代码为百问网的RA6M5 的驱动,我这里做了细小的改动而实现快速的驱动。
2 创建工程
在上一篇瑞萨RA0单片机连载之三基于面向对象的LED灯(刊载于《电子设计与芯片应用(10 月刊)》)的基础上添加串口的驱动。
1.本次驱动
选用的驱动的串口为r_sau_uart0, 配置的IO 为P100,P101 为TX 与RX。
打开RASC, 添加uart0添回串口回调函数为sau_uart_callback。并生成工程。
2.移植dev_uart.c/h、drv_uart.c/h 到工程中:
3. 其代码dev_uart.c 如下:
view plaincopy to clipboardprint?
1. #include “dev_uart.h”
2. #include
3.
4. #include
5. #include
6. #include
7.
8.
9. static struct UartDev *gHeadUartDev;
10.
11. void UartDevicesRegister(void)
12. {
13. UartDevicesCreate();
14. UartDeviceList();
15. }
16.
17. void UartDeviceInsert(struct UartDev *ptdev)
18. {
19. if(NULL == gHeadUartDev)
20. gHeadUartDev = ptdev;
21. else
22. {
23. ptdev->next = gHeadUartDev;
24. gHeadUartDev = ptdev;
25. }
26. }
27.
28. struct UartDev * UartDeviceFind(const char
*name)
29. {
30. struct UartDev *ptdev = gHeadUartDev;
31. while(ptdev)
unsigned char * const buf, unsigned int length);
19.
20. static volatile bool gUart0TxCplt = false;
21. static volatile bool gUart0RxCplt = false;
22.
23. static struct UartDev gLogDevice = {
24. .name = “Log”,
25. .channel = 0,
26. .Init = UARTDrvInit,
27. .Read = UARTDrvRead,
28. .Write = UARTDrvWrite,
29. .next = NULL
30. };
31.
32. void UartDevicesCreate(void)
33. {
34. UartDeviceInsert(&gLogDevice);
35. gLogDevice.Init(&gLogDevice);
36. }
37.
38. static int UARTDrvInit(struct UartDev *ptdev)
39. {
40. if(NULL == ptdev) return -EINVAL;
41.
42. switch(ptdev->channel)
43 {
44. case 0:
45. {
46. fsp_err_t err = g_uart0.p_api->open(g_
uart0.p_ctrl, g_uart0.p_cfg);
47. assert(FSP_SUCCESS == err);
48. break;
49. }
50.
51. case 1:case 2:
52. case 3:case 4:case 5:
53. case 6:
54. {
55. break;
56. }
57. case 7:
58.
59. case 8:case 9:
60. break;
61. default:break;
62. }
63.
64. return ESUCCESS;
65. }
66.
67. static int UARTDrvWrite(struct UartDev *ptdev,
unsigned char * const buf, unsigned int length)
68. {
69. if(NULL == ptdev) return -EINVAL;
70. if(NULL == buf) return -EINVAL;
71. if(0 == length) return -EINVAL;
72.
73. switch(ptdev->channel)
74. {
75. case 0:
76. {
77. fsp_err_t err = g_uart0.p_api->write(g_
uart0.p_ctrl, buf, length);
78. assert(FSP_SUCCESS == err);
79. UART0WaitTxCplt();
80. break;
81. }
82. case 1:case 2:
83. case 3:case 4:case 5:
84. case 6:
85. {
86. break;
87. }
88. case 7:
89.
90. case 8:case 9:
91. break;
92. default:break;
93. }
94. return ESUCCESS;
95. }
96. static int UARTDrvRead(struct UartDev *ptdev,
unsigned char *buf, unsigned int length)
97. {
98. if(NULL == ptdev) return -EINVAL;
99. if(NULL == buf) return -EINVAL;
100. if(0 == length) return -EINVAL;
101.
102. switch(ptdev->channel)
103. {
104. case 0:
105. {
106. fsp_err_t err = g_uart0.p_api->read(g_
uart0.p_ctrl, buf, length);
107. assert(FSP_SUCCESS == err);
108. UART0WaitRxCplt();
109. break;
110. }
111. case 1:case 2:
112. case 3:case 4:case 5:
113. case 6:
114. {
115. break;
116. }
117. case 7:
118.
119. case 8:case 9:
120. break;
121. default:break;
122. }
123.
124. return (int)length;
125. }
126.
127. void sau_uart_callback(uart_callback_args_
t * p_args)
128. {
129. switch(p_args->event)
130. {
131. case UART_EVENT_RX_COMPLETE:
132. {
133. gUart0RxCplt = true;
134. break;
135. }
136. case UART_EVENT_TX_COMPLETE:
137. {
138. gUart0TxCplt = true;
139. break;
140. }
141. case UART_EVENT_RX_CHAR:
142. {
143. break;
144. }
145. case UART_EVENT_ERR_PARITY:case
UART_EVENT_ERR_FRAMING:
146. case UART_EVENT_ERR_OVERFLOW:case
UART_EVENT_BREAK_DETECT:
147. case UART_EVENT_TX_DATA_EMPTY:
148. break;
149. default:break;
150. }
151. }
152.
153. static void UART0WaitTxCplt(void)
154. {
155. while(!gUart0TxCplt);
156. gUart0TxCplt = false;
157. }
158.
159. static void UART0WaitRxCplt(void)
160. {
161. while(!gUart0RxCplt);
162. gUart0RxCplt = false;
163. }
这里我们需要修改的地方就是对源码修改UART0的自几回调函数以及
view plaincopy to clipboardprint?
1. switch(ptdev->channel)
drv_uart.h
view plaincopy to clipboardprint?
1. /*
2. * drv_uart.h
3. *
4. * Created on: 2023 年4 月13 日
5. * Author: slhuan
6. */
7. #ifndef __DRV_UART_H
8. #defi ne __DRV_UART_H
9.
10. #define UART_DEVICE_NAME_MAX_
LENGTH (16)
11. #def ine UART_TOTAL_CHANNELS
(10)
12. #define UART_RECEIVE_BUFFER_SIZE
(1024)
13.
14. void UartDevicesCreate(void);
15.
16. #endif /* __DRV_UART_H */
到此为止,我们的驱动就移植完毕了。
测试代码:
实验效果,编译下载程序到开发板后,开机打印出初始化的LOG
3 总结
我们实现了面向对象的UART 的移植,从RA6M5的工程中移植过来,只需要修改少量的代码就可以实现面向对象的移植。
“掌”握科技鲜闻 (微信搜索techsina或扫描左侧二维码关注)