重要的事情说在前边
-
编写程序时,特别是C程序,应该也只有C程序。一定要 仔细 仔细 仔细 调用宏函数时传递的实参类型是否是被定义函数实际的参数类型。
比如传递指针,up 因为调用 API 时自以为是的传入指针导致程序跑不通,关键是既然可以成功编译,这就很无语。。。
这要 “得益于” 宏函数在预处理阶段只是简单的文本替换,并没有类型检查,这种问题连编译期都不会被检查到。
虽然不是像常规函数一样进行调用,无函数调用开销(如入栈、出栈等操作)。这使得宏函数在某些性能要求较高的情况下比普通函数更有效率。
但是这会导致调试时无法像常规函数一样查看调用栈、参数等信息。如果传递错误参数。。。并且是上万行的代码量。。。
或者在调用宏函数中有参数操作行为(比如计算同一个表达式 A(a++)),在预处理阶段就会执行,运行时再次执行,导致意外的结果,这种问题根本没法调试。。。
所以不建议使用宏函数,建议使用内联函数(inline)来代替宏函数,因为内联函数还可以进行类型检查、调试。 -
编译器要比你仔细,一定要注意 warning 并不是只有 error 才会导致错误,就是因为无视了 warning 也可以编译通过,才会在某些问题上止步不前。
-
少用全局变量,这会增加程序的可维护性和降低程序的可读性,全局变量可以被程序中的任何函数访问和修改,这使得代码的跟踪和调试变得非常困难。
很难确定某个特定函数是否会修改全局变量,从而可能引入错误或意外结果。并且对于弱需求的全局变量,会浪费内存资源。在多线程环境下还要考虑并发的问题。
最重要的是增加了程序的耦合性,当你发现一个全局变量并不符合现在的设计需求时,会浪费很多时间在修改不同程序中的同一个全局变量上。
同时多个函数依赖同一个全局变量(依赖同一个值)这本来就增加了函数的耦合性,不符合函数的单一最小化原则,和高内聚低耦合的要求,同时导致其他负面影响。
interface_uart.h
#ifndef __INTERFACE_UART_H__
#define __INTERFACE_UART_H__
/******************/
#define stm32_hal 1
#define stm32f4xx 0
#define stm32h5xx 1
#define CIRCLE_BUF_LEN 1000
#define BAREMETAL 0
#define FREERTOS 1
/******************/
#include "stdint.h"
#if BAREMETAL
#include "circle_buffer.h"
#elif FREERTOS
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
#endif
#if stm32f4xx
#include "stm32f4xx_hal.h"
#include "usart.h"
#elif stm32h5xx
#include "stm32h5xx_hal.h"
#include "usart.h"
#endif
#ifdef __cplusplus
extern "C"{
#endif
/**
* @brief
*/
typedef struct uart_init_s
{
uint32_t baud_rate;
uint8_t data_bits;
uint32_t stop_bits;
int32_t parity_bits;
uint32_t mode;
uint32_t flow_control;
/*
...
*/
} *p_uart_init, uart_init_t;
/**
* @brief
*/
typedef struct uart_device_s
{
int8_t *device_name;
#if stm32_hal
UART_HandleTypeDef *uart_handle;
#elif /* others */
/* others */
#else
struct uart_init_t *uart_init;
#endif
#if BAREMETAL
circle_buf_t *uart_buf_circle;
uint8_t *uart_buf_temp;
uint8_t *uart_buf_byte;
uint8_t uart_cplt_tx;
uint8_t uart_cplt_rx;
#elif FREERTOS
SemaphoreHandle_t *uart_semaphore_tx;
QueueHandle_t *uart_queue_rx;
uint8_t *uart_buf_rx;
#endif
} *p_uart_device, uart_device_t;
typedef struct uart_handle_s
{
// uart_device_t uart_dev;
uint8_t (*uart_init)(uart_device_t *pDev);
uint8_t (*uart_deinit)(uart_device_t *pDev);
uint8_t (*uart_receive)(uart_device_t *pDev);
uint8_t (*uart_transmit)(uart_device_t *pDev, uint8_t *buf, uint16_t len, uint16_t timeout);
uint8_t (*uart_get_byte)(uart_device_t *pDev, uint8_t *data, uint16_t timeout);
} *p_uart_handle, uart_handle_t;
#if FREERTOS
uint8_t uart_init_rtos(uart_device_t *pDev);
uint8_t uart_receive_rtos(uart_device_t *pDev);
uint8_t uart_transmit_rtos(uart_device_t *pDev, uint8_t *data, uint16_t len, uint16_t timeout);
uint8_t uart_get_byte_rtos(uart_device_t *pDev, uint8_t *data, uint16_t timeout);
#endif
#if BAREMETAL
uint8_t uart_init_baremetal(uart_device_t *pDev);
uint8_t uart_deinit_baremetal(uart_device_t *pDev);
uint8_t uart_receive_baremetal(uart_device_t *pDev);
uint8_t uart_transmit_baremetal(uart_device_t *pDev, uint8_t *buf, uint16_t len, uint16_t timeout);
uint8_t uart_transmit_by_it(uart_device_t *pDev , uint8_t *buf, uint16_t len, uint16_t timeout);
#endif
uint16_t uart_print(const int8_t *const fmt, ...);
uint8_t uart_test(void);
#ifdef __cplusplus
}
#endif
#endif
interface_uart.c
#include "interface_uart.h"
#include "stdio.h"
#include "string.h"
#include "stdarg.h"
/******************************************** freertos ***********************************************/
#if FREERTOS
uart_device_t *g_uart4_dev;
uart_handle_t *g_uart4_handle;
uart_device_t *g_uart2_dev;
uart_handle_t *g_uart2_handle;
uint8_t uart_init_rtos(uart_device_t *pDev)
{
// *(pDev->uart_semaphore_tx) = xSemaphoreCreateBinary();
// *(pDev->uart_queue_rx) = xQueueCreate(200, 1);
if (HAL_UARTEx_ReceiveToIdle_DMA(pDev->uart_handle, pDev->uart_buf_rx, 100) != HAL_OK)
{
return 1;
}
return 0;
}
uint8_t uart_receive_rtos(uart_device_t *pDev)
{
if (pDev == NULL)
{
return 2;
}
/* Receive an amount of data in DMA mode till either the expected number of data is received or an IDLE event occurs. */
if (HAL_UARTEx_ReceiveToIdle_DMA(pDev->uart_handle, pDev->uart_buf_rx, 100) != HAL_OK)
{
return 1;
}
return 0;
}
uint8_t uart_transmit_rtos(uart_device_t *pDev, uint8_t *data, uint16_t len, uint16_t timeout)
{
if (HAL_UART_Transmit_DMA(pDev->uart_handle, data, len) != HAL_OK)
{
return 1;
}
if (pdTRUE == xSemaphoreTake(*(pDev->uart_semaphore_tx), (uint32_t)timeout))
{
return 0;
}
else
{
return 2;
}
}
uint8_t uart_get_byte_rtos(uart_device_t *pDev, uint8_t *data, uint16_t timeout)
{
if (pdPASS == xQueueReceive(*(pDev->uart_queue_rx), (uint8_t*)data, (uint32_t)timeout))
{
return 0;
}
else
{
return 1;
}
}
#endif
/************************************ bare matel *************************************/
#if BAREMETAL
circle_buf_t g_uart2_buf_circle = {0};
uint8_t g_uart2_buf_rcv[CIRCLE_BUF_LEN] = {0};
uint8_t g_uart2_buf_temp[100] = {0};
uint8_t g_uart2_buf_byte = 0;
uart_device_t g_uart2_dev = {"uart2", &huart2, &g_uart2_buf_circle, &g_uart2_buf_temp, &g_uart2_buf_byte, 0, 0};
uart_handle_t g_uart2_handle = {0};
circle_buf_t g_uart4_buf_circle = {0};
uint8_t g_uart4_buf_rcv[CIRCLE_BUF_LEN] = {0};
uint8_t g_uart4_buf_temp[100] = {0};
uint8_t g_uart4_buf_byte = 0;
uart_device_t g_uart4_dev = {"uart4", &huart4, &g_uart4_buf_circle, &g_uart4_buf_temp, &g_uart4_buf_byte, 0, 0};
uart_handle_t g_uart4_handle = {0};
#endif
#if BAREMETAL
uint8_t uart_init_baremetal(uart_device_t *pDev)
{
if (pDev == NULL)
{
return 2;
}
/* 这里可以学习模仿 HAL 库在初始化 UART 时使用的 MX_UARTx_Init() 函数的实现 */
/*
huart4.Instance = UART4;
huart4.Init.BaudRate = 115200;
huart4.Init.WordLength = UART_WORDLENGTH_8B;
huart4.Init.StopBits = UART_STOPBITS_1;
huart4.Init.Parity = UART_PARITY_NONE;
huart4.Init.Mode = UART_MODE_TX_RX;
...
*/
/* 也可以学习 HAL 库将初始化参数都封装到 UART_InitTypeDef Init 这个结构体中,并提供一个 UART_HandleTypeDef 的句柄 */
/* 其中包括所要使用的 UART 设备的所有寄存器地址映射 USART_TypeDef, 初始化参数 UART_InitTypeDef, 进一步初始化的参数 UART_AdvFeatureInitTypeDef ... */
/* 初始化时创建 uart_handle_t uart4_handle 实例后 uart4.uart_init = interface_uart_init(&g_uart4_dev) 只需要调用通用的接口 uart4.uart_init 就可以实现 uart4 的初始化 */
/* 初始化后开启串口接收 */
// if (HAL_UARTEx_ReceiveToIdle_DMA(pDev->uart_handle, pDev->uart_buf_temp, 100) != HAL_OK)
// {
// return 1;
// }
return 0;
}
uint8_t uart_deinit_baremetal(uart_device_t *pDev)
{
if (HAL_UART_DeInit(pDev->uart_handle) != HAL_OK)
{
return 1;
}
return 0;
}
uint8_t uart_receive_baremetal(uart_device_t *pDev)
{
if (pDev == NULL)
{
return 2;
}
pDev->uart_cplt_rx = 0;
/* Receive an amount of data in DMA mode till either the expected number of data is received or an IDLE event occurs. */
if (HAL_UARTEx_ReceiveToIdle_DMA(pDev->uart_handle, pDev->uart_buf_temp, 100) != HAL_OK)
{
return 1;
}
return 0;
}
uint8_t uart_transmit_baremetal(uart_device_t *pDev, uint8_t *buf, uint16_t len, uint16_t timeout)
{
if (pDev == NULL || buf == NULL)
{
/* NULL pointer */
return 2;
}
if (timeout <= 0)
{
timeout = 65535;
}
/* clear transmission completion flag */
pDev->uart_cplt_tx = 0;
/* transmit using DMA */
if (HAL_UART_Transmit_DMA(pDev->uart_handle, (uint8_t*)buf, len) != HAL_OK)
{
/* HAL transmit failed */
return 1;
}
/* 可以用定时器创建自定义延时函数 */
uint32_t start_time = HAL_GetTick();
/* waiting for DMA transmission completion */
/* 注意:pDev->uart_tx_done 应在 HAL_UART_TxCpltCallback 回调中置为 1 */
while ((pDev->uart_cplt_tx == 0) && ((HAL_GetTick() - start_time) < timeout))
{
/* 空循环等待 */
__NOP();
}
if (pDev->uart_cplt_tx)
{
return 0;
}
else
{
/* timeout */
return 3;
}
}
uint8_t uart_transmit_by_it(uart_device_t *pDev , uint8_t *buf, uint16_t len, uint16_t timeout)
{
if (pDev == NULL || buf == NULL)
{
/* NULL pointer */
return 2;
}
timeout = 1000;
/* clear transmission completion interrupt flag */
pDev->uart_cplt_tx = 0;
/* transmit */
if (HAL_UART_Transmit_IT(pDev->uart_handle, (uint8_t*)buf, len) != HAL_OK)
{
/* HAL transmit failed */
return 1;
}
/* waiting for events */
/* 注意:pDev->uart_tx_done 应在 HAL_UART_TxCpltCallback 回调中置为 1 */
/* 方式一 */
// while((pDev->uart_tx_done == 0) && (timeout != 0))
// {
// HAL_Delay(1);
// timeout--;
// }
// /* check the timeout */
// if (timeout != 0)
// {
// /* return success */
// return 0;
// }
// else
// {
// /* timeout return failed */
// return 1;
// }
/* 方式二 减少 CPU 消耗 */
uint32_t start_time = HAL_GetTick();
while ((pDev->uart_cplt_tx == 0) && ((HAL_GetTick() - start_time) < timeout))
{
/* 空循环等待 */
__NOP();
}
if (pDev->uart_cplt_tx)
{
return 0;
}
else
{
/* timeout */
return 3;
}
}
#endif
/******************************************** Custom Implement ************************************************/
static inline void uart4_cplt_tx(void)
{
#if BAREMETAL
g_uart4_dev.uart_cplt_tx = 1;
#elif FREERTOS
xSemaphoreGiveFromISR(g_uart4_dev->uart_semaphore_tx, NULL);
#endif
}
static inline void uart2_cplt_tx(void)
{
#if BAREMETAL
g_uart2_dev.uart_cplt_tx = 1;
#elif FREERTOS
xSemaphoreGiveFromISR(g_uart2_dev->uart_semaphore_tx, NULL);
#endif
}
static inline void uart2_cplt_rx(void)
{
#if BAREMETAL
for (int i = 0; i < 100; i++)
{
circle_buf_write(g_uart2_dev.uart_buf_circle, g_uart2_dev.uart_buf_temp[i]);
}
g_uart2_dev.uart_cplt_rx = 1;
/* re-start DMA+IDLE rx */
HAL_UARTEx_ReceiveToIdle_DMA(g_uart2_dev.uart_handle, g_uart2_dev.uart_buf_temp, 100);
#elif FREERTOS
for (int i = 0; i < 100; i++)
{
xQueueSendFromISR(*(g_uart2_dev->uart_queue_rx), &(g_uart2_dev->uart_buf_rx[i]), NULL);
}
/* re-start DMA+IDLE rx */
HAL_UARTEx_ReceiveToIdle_DMA(g_uart2_dev->uart_handle, g_uart2_dev->uart_buf_rx, 100);
#endif
}
static inline void uart4_cplt_rx(void)
{
#if BAREMETAL
for (int i = 0; i < 100; i++)
{
circle_buf_write(g_uart4_dev.uart_buf_circle, g_uart4_dev.uart_buf_temp[i]);
}
g_uart4_dev.uart_cplt_rx = 1;
/* re-start DMA+IDLE rx */
HAL_UARTEx_ReceiveToIdle_DMA(g_uart4_dev.uart_handle, g_uart4_dev.uart_buf_temp, 100);
#elif FREERTOS
for (int i = 0; i < 100; i++)
{
xQueueSendFromISR(*(g_uart4_dev->uart_queue_rx), &(g_uart4_dev->uart_buf_rx[i]), NULL);
}
/* re-start DMA+IDLE rx */
HAL_UARTEx_ReceiveToIdle_DMA(g_uart4_dev->uart_handle, g_uart4_dev->uart_buf_rx, 100);
#endif
}
uint16_t uart_print(const int8_t *const fmt, ...)
{
int8_t str[512];
uint16_t len = 0;
va_list args;
memset(str, 0, sizeof(str));
va_start(args, fmt);
vsnprintf(str, sizeof(str) - 1, fmt, args);
va_end(args);
len = strlen(str);
if(interface_uart_transmit(&g_uart4_dev, str, len, 0) != 0)
{
return 0;
}
else
{
return len;
}
}
/************************************************ Uart Tset ************************************************/
uint8_t uart_test(void)
{
return 0;
}
/*************************************** IRQ Handler Callback Implement ***************************************/
/**
* @brief 发送完成中断回调函数
* @param huart
*/
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart == &huart4)
{
/* set transmission completion flag */
uart4_cplt_tx();
}
if (huart == &huart2)
{
/* set transmission completion flag */
uart2_cplt_tx();
}
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart == &huart2)
{
uart2_cplt_rx();
}
if (huart == &huart4)
{
uart4_cplt_rx();
}
}
/**
* @brief 接收事件中断回调函数(包括 IDLE Event 或 Rx the specified number of bytes)
* @param huart
* @param Size rx transfer size, number of bytes actually received
*/
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
if (huart == &huart4)
{
#if BAREMETAL
for (uint16_t i = 0; i < Size; i++)
{
circle_buf_write(g_uart4_dev.uart_buf_circle, g_uart4_dev.uart_buf_temp[i]);
}
HAL_UARTEx_ReceiveToIdle_DMA(g_uart4_dev.uart_handle, g_uart4_dev.uart_buf_temp, 100);
#elif FREERTOS
for (uint16_t i = 0; i < Size; i++)
{
xQueueSendFromISR(*(g_uart4_dev->uart_queue_rx), &(g_uart4_dev->uart_buf_rx[i]), NULL);
}
HAL_UARTEx_ReceiveToIdle_DMA(g_uart4_dev->uart_handle, g_uart4_dev->uart_buf_rx, 100);
#endif
}
if (huart == &huart2)
{
#if BAREMETAL
for (uint16_t i = 0; i < Size; i++)
{
circle_buf_write(g_uart2_dev.uart_buf_circle, g_uart2_dev.uart_buf_temp[i]);
}
HAL_UARTEx_ReceiveToIdle_DMA(g_uart2_dev.uart_handle, g_uart2_dev.uart_buf_temp, 100);
#elif FREERTOS
for (uint16_t i = 0; i < Size; i++)
{
xQueueSendFromISR(*(g_uart2_dev->uart_queue_rx), &(g_uart2_dev->uart_buf_rx[i]), NULL);
}
HAL_UARTEx_ReceiveToIdle_DMA(g_uart2_dev->uart_handle, g_uart2_dev->uart_buf_rx, 100);
#endif
}
}
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
if (huart == &huart2)
{
#if BAERMETAL
HAL_UARTEx_ReceiveToIdle_DMA(g_uart2_dev.uart_handle, g_uart2_dev.uart_buf_temp, 100);
#elif FREERTOS
HAL_UARTEx_ReceiveToIdle_DMA(g_uart2_dev->uart_handle, g_uart2_dev->uart_buf_rx, 100);
#endif
}
if (huart == &huart4)
{
#if BAERMETAL
HAL_UARTEx_ReceiveToIdle_DMA(g_uart4_dev.uart_handle, g_uart4_dev.uart_buf_temp, 100);
#elif FREERTOS
HAL_UARTEx_ReceiveToIdle_DMA(g_uart4_dev->uart_handle, g_uart4_dev->uart_buf_rx, 100);
#endif
}
}
circle_buffer.h
#ifndef __CIRCLE_BUF_H__
#define __CIRCLE_BUF_H__
#include <stdint.h>
#ifdef __cplusplus
extern "C"
{
#endif
typedef struct circle_buf_s
{
uint32_t r; /* 循环buf 的队头 */
uint32_t w; /* 循环buf 的队尾 */
uint8_t *buf;
uint32_t len;
} *p_circle_buf_t, circle_buf_t;
void circle_buf_init(p_circle_buf_t pCircleBuf, uint8_t *buf, uint32_t len);
int circle_buf_read(p_circle_buf_t pCircleBuf, uint8_t *pVal);
int circle_buf_write(p_circle_buf_t pCircleBuf, uint8_t val);
#ifdef __cplusplus
}
#endif
#endif /* __CIRCLE_BUF_H__ */
circle_buffer.c
#include "circle_buffer.h"
/**
* @brief 初始化循环队列 buffer
* @param pCircleBuf
* @param len
* @param buf
*/
void circle_buf_init(p_circle_buf_t pCircleBuf, uint8_t *buf, uint32_t len)
{
pCircleBuf->r = pCircleBuf->w = 0;
pCircleBuf->len = len;
pCircleBuf->buf = buf;
}
/**
* @brief 判断循环队列 buffer 是否为空
* @param pCircleBuf
* @return
*/
int circle_buf_is_empty(p_circle_buf_t pCircleBuf)
{
return (pCircleBuf->r == pCircleBuf->w);
}
/**
* @brief 判断循环队列 buffer 是否满
* @param pCircleBuf
* @return
*/
int circle_buf_is_full(p_circle_buf_t pCircleBuf)
{
return (pCircleBuf->w + 1) % pCircleBuf->len == pCircleBuf->r;
}
/**
* @brief 循环队列 buf 出队操作
* @param pCircleBuf
* @param pVal
* @return
*/
int circle_buf_read(p_circle_buf_t pCircleBuf, uint8_t *pVal)
{
if (circle_buf_is_empty(pCircleBuf)) /* 如果循环buf 为空 */
{
return -1; /* buf为空,读取失败 */
}
*pVal = pCircleBuf->buf[pCircleBuf->r];
pCircleBuf->r = (pCircleBuf->r + 1) % pCircleBuf->len;
return 0;
}
/**
* @brief 循环队列 buf 入队操作
* @param pCircleBuf
* @param val
* @return
*/
int circle_buf_write(p_circle_buf_t pCircleBuf, uint8_t val)
{
if (circle_buf_is_full(pCircleBuf)) /* 如果循环buf 已满 */
{
return -1; /* buf已满,写入失败 */
}
pCircleBuf->buf[pCircleBuf->w] = val;
pCircleBuf->w = (pCircleBuf->w + 1) % pCircleBuf->len;
return 0;
}
main.c
extern uart_device_t *g_uart4_dev;
extern uart_handle_t *g_uart4_handle;
extern uart_device_t *g_uart2_dev;
extern uart_handle_t *g_uart2_handle;
/************** 测串 uart *************** */
QueueHandle_t uart4_queue_rx;
SemaphoreHandle_t uart4_semaphore_tx;
g_uart4_dev = (uart_device_t*)malloc(sizeof(uart_device_t));
g_uart4_dev->device_name = (int8_t*)"uart4";
g_uart4_dev->uart_handle = &huart4;
g_uart4_dev->uart_buf_rx = (uint8_t*)malloc(sizeof(uint8_t)*100);
uart4_queue_rx = xQueueCreate(200, 1);
g_uart4_dev->uart_queue_rx = &uart4_queue_rx ;
uart4_semaphore_tx = xSemaphoreCreateBinary();
g_uart4_dev->uart_semaphore_tx = &uart4_semaphore_tx;
g_uart4_handle = (uart_handle_t*)malloc(sizeof(uart_handle_t));
g_uart4_handle->uart_init = uart_init_rtos;
g_uart4_handle->uart_receive = uart_receive_rtos;
g_uart4_handle->uart_transmit = uart_transmit_rtos;
g_uart4_handle->uart_get_byte = uart_get_byte_rtos;
QueueHandle_t uart2_queue_rx;
SemaphoreHandle_t uart2_semaphore_tx;
g_uart2_dev = (uart_device_t*)malloc(sizeof(uart_device_t));
g_uart2_dev->device_name = (int8_t*)"uart2";
g_uart2_dev->uart_handle = &huart2;
g_uart2_dev->uart_buf_rx = (uint8_t*)malloc(sizeof(uint8_t)*100);
uart2_queue_rx = xQueueCreate(200, 1);
g_uart2_dev->uart_queue_rx = &uart2_queue_rx ;
uart2_semaphore_tx = xSemaphoreCreateBinary();
g_uart2_dev->uart_semaphore_tx = &uart2_semaphore_tx;
g_uart2_handle = (uart_handle_t*)malloc(sizeof(uart_handle_t));
g_uart2_handle->uart_init = uart_init_rtos;
g_uart2_handle->uart_receive = uart_receive_rtos;
g_uart2_handle->uart_transmit = uart_transmit_rtos;
g_uart2_handle->uart_get_byte = uart_get_byte_rtos;
rtostask
static void CH1_UART2_TxTaskFunction(void *pvParameters)
{
uint8_t c = 0;
g_uart2_handle->uart_init(g_uart2_dev);
while (1)
{
/* send data */
g_uart2_handle->uart_transmit(g_uart2_dev, &c, 1, 100);
vTaskDelay(100);
c++;
}
}
static void CH2_UART4_RxTaskFunction(void *pvParameters)
{
uint8_t c = 0;
int cnt = 0;
char buf[100];
g_uart4_handle->uart_init(g_uart4_dev);
/* 接收数据 */
g_uart4_handle->uart_receive(g_uart4_dev);
while (1)
{
g_uart4_handle->uart_get_byte(g_uart4_dev, &c, 200);
sprintf(buf, "Recv Data : 0x%02x, Cnt : %d", c, cnt++);
Draw_String(0, 0, buf, 0x0000ff00, 0);
}
}