串口是单片机最常用的外设之一。本次创建面向对象来移植UART的驱动。
【学习例程】百问网的面向对象的这UART驱动,源代码为百问网的RA6M5的驱动,我这里做了细小的改动而实现快速的驱动。
【创建工程】
在上一篇瑞萨RA0单片机连载之三基于面向对象的LED灯-电子产品世界论坛 (eepw.com.cn)的基础上添加串口的驱动。
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如下:
#include "dev_uart.h"
#include <drivers.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
static struct UartDev *gHeadUartDev;
void UartDevicesRegister(void)
{
UartDevicesCreate();
UartDeviceList();
}
void UartDeviceInsert(struct UartDev *ptdev)
{
if(NULL == gHeadUartDev)
gHeadUartDev = ptdev;
else
{
ptdev->next = gHeadUartDev;
gHeadUartDev = ptdev;
}
}
struct UartDev *UartDeviceFind(const char *name)
{
struct UartDev *ptdev = gHeadUartDev;
while(ptdev)
{
if(strstr(ptdev->name, name))
{
return ptdev;
}
ptdev = ptdev->next;
}
return NULL;
}
void UartDeviceList(void)
{
struct UartDev *ptdev = gHeadUartDev;
printf("\r\nUart Device List:\r\n");
while(ptdev)
{
printf("\t%s\r\n", ptdev->name);
ptdev = ptdev->next;
}
printf("\r\n");
}其代码dev_uart.h如下:
/*
* dev_uart.h
*
* Created on: 2023?4?13?
* Author: slhuan
*/
#ifndef __DEV_UART_H
#define __DEV_UART_H
typedef struct UartDev{
char *name;
unsigned char channel;
int (*Init)(struct UartDev *ptdev);
int (*Write)(struct UartDev *ptdev, unsigned char * const buf, unsigned int length);
int (*Read)(struct UartDev *ptdev, unsigned char *buf, unsigned int length);
struct UartDev *next;
}UartDevice;
void UartDevicesRegister(void);
void UartDeviceInsert(struct UartDev *ptdev);
struct UartDev *UartDeviceFind(const char *name);
void UartDeviceList(void);
#endif /* __DEV_UART_H */drv_uart.c代码如下:
/*
* drv_uart.c
*
* Created on: 2023年3月30日
* Author: slhuan
*/
#include "drv_uart.h"
#include <devices.h>
#include "hal_data.h"
#include <errno.h>
static void UART0WaitTxCplt(void);
static void UART0WaitRxCplt(void);
static int UARTDrvInit(struct UartDev *ptdev);
static int UARTDrvRead(struct UartDev *ptdev, unsigned char *buf, unsigned int length);
static int UARTDrvWrite(struct UartDev *ptdev, unsigned char * const buf, unsigned int length);
static volatile bool gUart0TxCplt = false;
static volatile bool gUart0RxCplt = false;
static struct UartDev gLogDevice = {
.name = "Log",
.channel = 0,
.Init = UARTDrvInit,
.Read = UARTDrvRead,
.Write = UARTDrvWrite,
.next = NULL
};
void UartDevicesCreate(void)
{
UartDeviceInsert(&gLogDevice);
gLogDevice.Init(&gLogDevice);
}
static int UARTDrvInit(struct UartDev *ptdev)
{
if(NULL == ptdev) return -EINVAL;
switch(ptdev->channel)
{
case 0:
{
fsp_err_t err = g_uart0.p_api->open(g_uart0.p_ctrl, g_uart0.p_cfg);
assert(FSP_SUCCESS == err);
break;
}
case 1:case 2:
case 3:case 4:case 5:
case 6:
{
break;
}
case 7:
case 8:case 9:
break;
default:break;
}
return ESUCCESS;
}
static int UARTDrvWrite(struct UartDev *ptdev, unsigned char * const buf, unsigned int length)
{
if(NULL == ptdev) return -EINVAL;
if(NULL == buf) return -EINVAL;
if(0 == length) return -EINVAL;
switch(ptdev->channel)
{
case 0:
{
fsp_err_t err = g_uart0.p_api->write(g_uart0.p_ctrl, buf, length);
assert(FSP_SUCCESS == err);
UART0WaitTxCplt();
break;
}
case 1:case 2:
case 3:case 4:case 5:
case 6:
{
break;
}
case 7:
case 8:case 9:
break;
default:break;
}
return ESUCCESS;
}
static int UARTDrvRead(struct UartDev *ptdev, unsigned char *buf, unsigned int length)
{
if(NULL == ptdev) return -EINVAL;
if(NULL == buf) return -EINVAL;
if(0 == length) return -EINVAL;
switch(ptdev->channel)
{
case 0:
{
fsp_err_t err = g_uart0.p_api->read(g_uart0.p_ctrl, buf, length);
assert(FSP_SUCCESS == err);
UART0WaitRxCplt();
break;
}
case 1:case 2:
case 3:case 4:case 5:
case 6:
{
break;
}
case 7:
case 8:case 9:
break;
default:break;
}
return (int)length;
}
void sau_uart_callback(uart_callback_args_t * p_args)
{
switch(p_args->event)
{
case UART_EVENT_RX_COMPLETE:
{
gUart0RxCplt = true;
break;
}
case UART_EVENT_TX_COMPLETE:
{
gUart0TxCplt = true;
break;
}
case UART_EVENT_RX_CHAR:
{
break;
}
case UART_EVENT_ERR_PARITY:case UART_EVENT_ERR_FRAMING:
case UART_EVENT_ERR_OVERFLOW:case UART_EVENT_BREAK_DETECT:
case UART_EVENT_TX_DATA_EMPTY:
break;
default:break;
}
}
static void UART0WaitTxCplt(void)
{
while(!gUart0TxCplt);
gUart0TxCplt = false;
}
static void UART0WaitRxCplt(void)
{
while(!gUart0RxCplt);
gUart0RxCplt = false;
}这里我们需要修改的地方就是对源码修改UART0的自几回调函数以及
switch(ptdev->channel)
drv_uart.h
/* * drv_uart.h * * Created on: 2023年4月13日 * Author: slhuan */ #ifndef __DRV_UART_H #define __DRV_UART_H #define UART_DEVICE_NAME_MAX_LENGTH (16) #define UART_TOTAL_CHANNELS (10) #define UART_RECEIVE_BUFFER_SIZE (1024) void UartDevicesCreate(void); #endif /* __DRV_UART_H */
到此为止,我们的驱动就移植完毕了。
测试代码:

实验效果,编译下载程序到开发板后,开机打印出初始化的LOG

【总结】
我们实现了面向对象的UART的移植,从RA6M5的工程中移植过来,只需要修改少量的代码就可以实现面向对象的移植。
我要赚赏金
