收藏一些好用的c语言数据结构

Redis链表与环形缓冲

14、redis内置的链表,非常好

adlist.c

/* adlist.c - A generic doubly linked list implementation
 *
 * Copyright (c) 2006-2010, Salvatore Sanfilippo <antirez at gmail dot com>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   * Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *   * Neither the name of Redis nor the names of its contributors may be used
 *     to endorse or promote products derived from this software without
 *     specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */


#include <stdlib.h>
#include "adlist.h"

/* Create a new list. The created list can be freed with
 * AlFreeList(), but private value of every node need to be freed
 * by the user before to call AlFreeList().
 *
 * On error, NULL is returned. Otherwise the pointer to the new list. */
list *listCreate(void)
{
    struct list *list;

    if ((list = malloc(sizeof(*list))) == NULL)
        return NULL;
    list->head = list->tail = NULL;
    list->len = 0;
    list->dup = NULL;
    list->free = NULL;
    list->match = NULL;
    return list;
}

/* Remove all the elements from the list without destroying the list itself. */
void listEmpty(list *list)
{
    unsigned long len;
    listNode *current, *next;

    current = list->head;
    len = list->len;
    while(len--) {
        next = current->next;
        if (list->free) list->free(current->value);
        free(current);
        current = next;
    }
    list->head = list->tail = NULL;
    list->len = 0;
}

/* Free the whole list.
 *
 * This function can't fail. */
void listRelease(list *list)
{
    listEmpty(list);
    free(list);
}

/* Add a new node to the list, to head, containing the specified 'value'
 * pointer as value.
 *
 * On error, NULL is returned and no operation is performed (i.e. the
 * list remains unaltered).
 * On success the 'list' pointer you pass to the function is returned. */
list *listAddNodeHead(list *list, void *value)
{
    listNode *node;

    if ((node = malloc(sizeof(*node))) == NULL)
        return NULL;
    node->value = value;
    if (list->len == 0) {
        list->head = list->tail = node;
        node->prev = node->next = NULL;
    } else {
        node->prev = NULL;
        node->next = list->head;
        list->head->prev = node;
        list->head = node;
    }
    list->len++;
    return list;
}

/* Add a new node to the list, to tail, containing the specified 'value'
 * pointer as value.
 *
 * On error, NULL is returned and no operation is performed (i.e. the
 * list remains unaltered).
 * On success the 'list' pointer you pass to the function is returned. */
list *listAddNodeTail(list *list, void *value)
{
    listNode *node;

    if ((node = malloc(sizeof(*node))) == NULL)
        return NULL;
    node->value = value;
    if (list->len == 0) {
        list->head = list->tail = node;
        node->prev = node->next = NULL;
    } else {
        node->prev = list->tail;
        node->next = NULL;
        list->tail->next = node;
        list->tail = node;
    }
    list->len++;
    return list;
}

list *listInsertNode(list *list, listNode *old_node, void *value, int after) {
    listNode *node;

    if ((node = malloc(sizeof(*node))) == NULL)
        return NULL;
    node->value = value;
    if (after) {
        node->prev = old_node;
        node->next = old_node->next;
        if (list->tail == old_node) {
            list->tail = node;
        }
    } else {
        node->next = old_node;
        node->prev = old_node->prev;
        if (list->head == old_node) {
            list->head = node;
        }
    }
    if (node->prev != NULL) {
        node->prev->next = node;
    }
    if (node->next != NULL) {
        node->next->prev = node;
    }
    list->len++;
    return list;
}

/* Remove the specified node from the specified list.
 * It's up to the caller to free the private value of the node.
 *
 * This function can't fail. */
void listDelNode(list *list, listNode *node)
{
    if (node->prev)
        node->prev->next = node->next;
    else
        list->head = node->next;
    if (node->next)
        node->next->prev = node->prev;
    else
        list->tail = node->prev;
    if (list->free) list->free(node->value);
    free(node);
    list->len--;
}

/* Returns a list iterator 'iter'. After the initialization every
 * call to listNext() will return the next element of the list.
 *
 * This function can't fail. */
listIter *listGetIterator(list *list, int direction)
{
    listIter *iter;

    if ((iter = malloc(sizeof(*iter))) == NULL) return NULL;
    if (direction == AL_START_HEAD)
        iter->next = list->head;
    else
        iter->next = list->tail;
    iter->direction = direction;
    return iter;
}

/* Release the iterator memory */
void listReleaseIterator(listIter *iter) {
    free(iter);
}

/* Create an iterator in the list private iterator structure */
void listRewind(list *list, listIter *li) {
    li->next = list->head;
    li->direction = AL_START_HEAD;
}

void listRewindTail(list *list, listIter *li) {
    li->next = list->tail;
    li->direction = AL_START_TAIL;
}

/* Return the next element of an iterator.
 * It's valid to remove the currently returned element using
 * listDelNode(), but not to remove other elements.
 *
 * The function returns a pointer to the next element of the list,
 * or NULL if there are no more elements, so the classical usage patter
 * is:
 *
 * iter = listGetIterator(list,<direction>);
 * while ((node = listNext(iter)) != NULL) {
 *     doSomethingWith(listNodeValue(node));
 * }
 *
 * */
listNode *listNext(listIter *iter)
{
    listNode *current = iter->next;

    if (current != NULL) {
        if (iter->direction == AL_START_HEAD)
            iter->next = current->next;
        else
            iter->next = current->prev;
    }
    return current;
}

/* Duplicate the whole list. On out of memory NULL is returned.
 * On success a copy of the original list is returned.
 *
 * The 'Dup' method set with listSetDupMethod() function is used
 * to copy the node value. Otherwise the same pointer value of
 * the original node is used as value of the copied node.
 *
 * The original list both on success or error is never modified. */
list *listDup(list *orig)
{
    list *copy;
    listIter iter;
    listNode *node;

    if ((copy = listCreate()) == NULL)
        return NULL;
    copy->dup = orig->dup;
    copy->free = orig->free;
    copy->match = orig->match;
    listRewind(orig, &iter);
    while((node = listNext(&iter)) != NULL) {
        void *value;

        if (copy->dup) {
            value = copy->dup(node->value);
            if (value == NULL) {
                listRelease(copy);
                return NULL;
            }
        } else
            value = node->value;
        if (listAddNodeTail(copy, value) == NULL) {
            listRelease(copy);
            return NULL;
        }
    }
    return copy;
}

/* Search the list for a node matching a given key.
 * The match is performed using the 'match' method
 * set with listSetMatchMethod(). If no 'match' method
 * is set, the 'value' pointer of every node is directly
 * compared with the 'key' pointer.
 *
 * On success the first matching node pointer is returned
 * (search starts from head). If no matching node exists
 * NULL is returned. */
listNode *listSearchKey(list *list, void *key)
{
    listIter iter;
    listNode *node;

    listRewind(list, &iter);
    while((node = listNext(&iter)) != NULL) {
        if (list->match) {
            if (list->match(node->value, key)) {
                return node;
            }
        } else {
            if (key == node->value) {
                return node;
            }
        }
    }
    return NULL;
}

/* Return the element at the specified zero-based index
 * where 0 is the head, 1 is the element next to head
 * and so on. Negative integers are used in order to count
 * from the tail, -1 is the last element, -2 the penultimate
 * and so on. If the index is out of range NULL is returned. */
listNode *listIndex(list *list, long index) {
    listNode *n;

    if (index < 0) {
        index = (-index)-1;
        n = list->tail;
        while(index-- && n) n = n->prev;
    } else {
        n = list->head;
        while(index-- && n) n = n->next;
    }
    return n;
}

/* Rotate the list removing the tail node and inserting it to the head. */
void listRotate(list *list) {
    listNode *tail = list->tail;

    if (listLength(list) <= 1) return;

    /* Detach current tail */
    list->tail = tail->prev;
    list->tail->next = NULL;
    /* Move it as head */
    list->head->prev = tail;
    tail->prev = NULL;
    tail->next = list->head;
    list->head = tail;
}

/* Add all the elements of the list 'o' at the end of the
 * list 'l'. The list 'other' remains empty but otherwise valid. */
void listJoin(list *l, list *o) {
    if (o->head)
        o->head->prev = l->tail;

    if (l->tail)
        l->tail->next = o->head;
    else
        l->head = o->head;

    if (o->tail) l->tail = o->tail;
    l->len += o->len;

    /* Setup other as an empty list. */
    o->head = o->tail = NULL;
    o->len = 0;
}

 

adlist.h

/* adlist.h - A generic doubly linked list implementation
 *
 * Copyright (c) 2006-2012, Salvatore Sanfilippo <antirez at gmail dot com>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   * Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *   * Neither the name of Redis nor the names of its contributors may be used
 *     to endorse or promote products derived from this software without
 *     specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef __ADLIST_H__
#define __ADLIST_H__

/* Node, List, and Iterator are the only data structures used currently. */

typedef struct listNode {
    struct listNode *prev;
    struct listNode *next;
    void *value;
} listNode;

typedef struct listIter {
    listNode *next;
    int direction;
} listIter;

typedef struct list {
    listNode *head;
    listNode *tail;
    void *(*dup)(void *ptr);
    void (*free)(void *ptr);
    int (*match)(void *ptr, void *key);
    unsigned long len;
} list;

/* Functions implemented as macros */
#define listLength(l) ((l)->len)
#define listFirst(l) ((l)->head)
#define listLast(l) ((l)->tail)
#define listPrevNode(n) ((n)->prev)
#define listNextNode(n) ((n)->next)
#define listNodeValue(n) ((n)->value)

#define listSetDupMethod(l,m) ((l)->dup = (m))
#define listSetFreeMethod(l,m) ((l)->free = (m))
#define listSetMatchMethod(l,m) ((l)->match = (m))

#define listGetDupMethod(l) ((l)->dup)
#define listGetFree(l) ((l)->free)
#define listGetMatchMethod(l) ((l)->match)

/* Prototypes */
list *listCreate(void);
void listRelease(list *list);
void listEmpty(list *list);
list *listAddNodeHead(list *list, void *value);
list *listAddNodeTail(list *list, void *value);
list *listInsertNode(list *list, listNode *old_node, void *value, int after);
void listDelNode(list *list, listNode *node);
listIter *listGetIterator(list *list, int direction);
listNode *listNext(listIter *iter);
void listReleaseIterator(listIter *iter);
list *listDup(list *orig);
listNode *listSearchKey(list *list, void *key);
listNode *listIndex(list *list, long index);
void listRewind(list *list, listIter *li);
void listRewindTail(list *list, listIter *li);
void listRotate(list *list);
void listJoin(list *l, list *o);

/* Directions for iterators */
#define AL_START_HEAD 0
#define AL_START_TAIL 1

#endif /* __ADLIST_H__ */

 

13、嵌入式非常不错的环形缓冲

Generic ring buffer manager library

https://github.com/MaJerle/ringbuff

a ring buffer like kfifo, work in linux kernel and user space, test on kernel 3.16 on both x86 and ARM platform

https://github.com/dennis-musk/ringbuffer

 

12、A ring buffer implemented in C

https://github.com/dhess/c-ringbuf

https://github.com/XinLiGH/RingBuffer

 

 

11、Just a dead simple set of c macros for working with ring buffers in a generic manner.

https://github.com/pthrasher/c-generic-ring-buffer

 

10、fifo

https://github.com/resset/fifo

 

9、A thread safe type-agnostic header-only macro-based struct queue implementation in C.

https://github.com/nullseed/queue

 

8、ring_queue

https://github.com/dodng/fast_ring_queue

 

7、fifo

https://github.com/geekfactory/FIFO

 

6、list

https://github.com/clibs/list

 

5、栈

https://blog.youkuaiyun.com/TECH_PRO/article/details/72930404

 

4 从nodejs底层框架libuv源码中发现一个高效的C语言队列

https://www.oschina.net/code/snippet_2373320_52425

 

3、Linux内核链表-通用链表的实现

https://www.cnblogs.com/kanite/p/5833492.html

https://www.cnblogs.com/westfly/archive/2011/04/07/2007549.html

实例1:

选自https://blog.youkuaiyun.com/codeTZ/article/details/53229439

实例2:

选自http://blog.sina.com.cn/s/blog_70a1af020100rnbh.html

 

2、Nordic库中的 E:\nRF52_SDK_0.9.2_dbc28c9\components\libraries\fifo

app_fifo.c

#include <stdbool.h>
#include "app_fifo.h"

bool is_power_of_two(uint32_t n)
{
    if(n<=0)
        return false;
    return (n&(n-1))==0;
}

static uint32_t fifo_length(app_fifo_t * p_fifo)
{
  uint32_t tmp = p_fifo->read_pos;
  return p_fifo->write_pos - tmp;
}

#define FIFO_LENGTH fifo_length(p_fifo)  /**< Macro for calculating the FIFO length. */


uint32_t app_fifo_init(app_fifo_t * p_fifo, uint8_t * p_buf, uint16_t buf_size)
{
    // Check buffer for null pointer.
    if (p_buf == NULL)
    {
        return ERROR_NULL;
    }

    // Check that the buffer size is a power of two.
    if (!is_power_of_two(buf_size))
    {
        return ERROR_INVALID_LENGTH;
    }

    p_fifo->p_buf         = p_buf;
    p_fifo->buf_size_mask = buf_size - 1;
    p_fifo->read_pos      = 0;
    p_fifo->write_pos     = 0;

    return SUCCESS;
}


uint32_t app_fifo_put(app_fifo_t * p_fifo, uint8_t byte)
{
    if (FIFO_LENGTH <= p_fifo->buf_size_mask)
    {
        p_fifo->p_buf[p_fifo->write_pos & p_fifo->buf_size_mask] = byte;
        p_fifo->write_pos++;
        return SUCCESS;
    }

    return ERROR_NO_MEM;
}

uint32_t app_fifo_get(app_fifo_t * p_fifo, uint8_t * p_byte)
{
    if (FIFO_LENGTH != 0)
    {
        *p_byte = p_fifo->p_buf[p_fifo->read_pos & p_fifo->buf_size_mask];
        p_fifo->read_pos++;
        return SUCCESS;
    }

    return ERROR_NOT_FOUND;

}

uint32_t app_fifo_flush(app_fifo_t * p_fifo)
{
    p_fifo->read_pos = p_fifo->write_pos;
    return SUCCESS;
}

app_fifo.h

/**@file
 *
 * @defgroup app_fifo FIFO implementation
 * @{
 * @ingroup app_common
 *
 * @brief FIFO implementation.
 */

#ifndef APP_FIFO_H__
#define APP_FIFO_H__

#include <stdint.h>
#include <stdlib.h>

enum {
    SUCCESS,
    ERROR_NULL,
    ERROR_INVALID_LENGTH,
    ERROR_NO_MEM,
    ERROR_NOT_FOUND

};

/**@brief A FIFO instance structure. Keeps track of which bytes to read and write next.
 *        Also it keeps the information about which memory is allocated for the buffer
 *        and its size. This needs to be initialized by app_fifo_init() before use.
 */
typedef struct
{
    uint8_t *          p_buf;           /**< Pointer to FIFO buffer memory.                      */
    uint16_t           buf_size_mask;   /**< Read/write index mask. Also used for size checking. */
    volatile uint32_t  read_pos;        /**< Next read position in the FIFO buffer.              */
    volatile uint32_t  write_pos;       /**< Next write position in the FIFO buffer.             */
} app_fifo_t;

/**@brief Function for initializing the FIFO.
 *
 * @param[out] p_fifo   FIFO object.
 * @param[in]  p_buf    FIFO buffer for storing data. The buffer size has to be a power of two.
 * @param[in]  buf_size Size of the FIFO buffer provided, has to be a power of 2.
 *
 * @retval     SUCCESS              If initialization was successful.
 * @retval     ERROR_NULL           If a NULL pointer is provided as buffer.
 * @retval     ERROR_INVALID_LENGTH If size of buffer provided is not a power of two.
 */
uint32_t app_fifo_init(app_fifo_t * p_fifo, uint8_t * p_buf, uint16_t buf_size);

/**@brief Function for adding an element to the FIFO.
 *
 * @param[in]  p_fifo   Pointer to the FIFO.
 * @param[in]  byte     Data byte to add to the FIFO.
 *
 * @retval     SUCCESS              If an element has been successfully added to the FIFO.
 * @retval     ERROR_NO_MEM         If the FIFO is full.
 */
uint32_t app_fifo_put(app_fifo_t * p_fifo, uint8_t byte);

/**@brief Function for getting the next element from the FIFO.
 *
 * @param[in]  p_fifo   Pointer to the FIFO.
 * @param[out] p_byte   Byte fetched from the FIFO.
 *
 * @retval     SUCCESS              If an element was returned.
 * @retval     ERROR_NOT_FOUND      If there is no more elements in the queue.
 */
uint32_t app_fifo_get(app_fifo_t * p_fifo, uint8_t * p_byte);

/**@brief Function for flushing the FIFO.
 *
 * @param[in]  p_fifo   Pointer to the FIFO.
 *
 * @retval     SUCCESS              If the FIFO flushed successfully.
 */
uint32_t app_fifo_flush(app_fifo_t * p_fifo);

#endif // APP_FIFO_H__

/** @} */

main.c

#include <stdio.h>
#include <stdlib.h>
#include "app_fifo.h"

#define WS_BUF_LEN 1024
uint8_t ws_buf[WS_BUF_LEN];

app_fifo_t ws_fifo;

int main()
{
    uint32_t ws_fifo_status=app_fifo_init(&ws_fifo, ws_buf, 64);

    printf("ws_fifo_status: %d! \n" , ws_fifo_status);

    ws_fifo_status=app_fifo_put(&ws_fifo, 0x55);

    uint8_t p_ws_byte ;

    ws_fifo_status=app_fifo_get(&ws_fifo, &p_ws_byte);

    printf("data = 0x%x \n",p_ws_byte);

    printf("data = 0x%x \n",ws_buf[0]);

    return 0;
}

 

改造一下,支持多字节操作

app_fifo.c

#include <stdbool.h>
#include "app_fifo.h"

bool is_power_of_two(uint32_t n)
{
    if(n<=0)
        return false;
    return (n&(n-1))==0;
}

uint32_t fifo_length(app_fifo_t * p_fifo)
{
  uint32_t tmp = p_fifo->read_pos;
  return p_fifo->write_pos - tmp;
}

#define FIFO_LENGTH fifo_length(p_fifo)  /**< Macro for calculating the FIFO length. */


uint32_t app_fifo_init(app_fifo_t * p_fifo, uint16_t buf_size)
{
    //p_fifo->p_buf         = p_buf;
    p_fifo->buf_size_mask = buf_size - 1;
    p_fifo->read_pos      = 0;
    p_fifo->write_pos     = 0;

    return SUCCESS;
}


uint32_t app_fifo_put(app_fifo_t * p_fifo, uint8_t byte)
{
    if (FIFO_LENGTH <= p_fifo->buf_size_mask)
    {
        p_fifo->p_buf[p_fifo->write_pos & p_fifo->buf_size_mask] = byte;
        p_fifo->write_pos++;
        return SUCCESS;
    }

    return ERROR_NO_MEM;
}

uint32_t app_fifo_get(app_fifo_t * p_fifo, uint8_t * p_byte)
{
    if (FIFO_LENGTH != 0)
    {
        *p_byte = p_fifo->p_buf[p_fifo->read_pos & p_fifo->buf_size_mask];
        p_fifo->read_pos++;
        return SUCCESS;
    }

    return ERROR_NOT_FOUND;

}

uint32_t app_fifo_put_multiple(app_fifo_t * p_fifo, uint8_t* data, uint8_t len)
{
    if (FIFO_LENGTH <= p_fifo->buf_size_mask)
    {   /*
        memcpy(&(p_fifo->p_buf[p_fifo->write_pos & p_fifo->buf_size_mask]),data,len);
        //p_fifo->p_buf[p_fifo->write_pos & p_fifo->buf_size_mask] = byte;
        p_fifo->write_pos+len;
        */
        int i;
        for(i=0;i<len;i++)
            app_fifo_put(p_fifo, data[i]);
        return SUCCESS;
    }

    return ERROR_NO_MEM;
}

uint32_t app_fifo_get_multiple(app_fifo_t * p_fifo, uint8_t * data, uint8_t len)
{
    if (FIFO_LENGTH >= len)
    {   /*
        memcpy(data,&(p_fifo->p_buf[p_fifo->write_pos & p_fifo->buf_size_mask]),len);
        //*p_byte = p_fifo->p_buf[p_fifo->read_pos & p_fifo->buf_size_mask];
        p_fifo->read_pos+len;
        */
        int i;
        for(i=0;i<len;i++)
            app_fifo_get(p_fifo, &data[i]);
        return SUCCESS;
    }

    return ERROR_NOT_FOUND;

}

uint32_t app_fifo_flush(app_fifo_t * p_fifo)
{
    p_fifo->read_pos = p_fifo->write_pos;
    return SUCCESS;
}

app_fifo.h

/**@file
 *
 * @defgroup app_fifo FIFO implementation
 * @{
 * @ingroup app_common
 *
 * @brief FIFO implementation.
 */

#ifndef APP_FIFO_H__
#define APP_FIFO_H__

#include <stdint.h>
#include <stdlib.h>

#define FIFO_BUF_LEN 1024

enum {
    SUCCESS,
    ERROR_NULL,
    ERROR_INVALID_LENGTH,
    ERROR_NO_MEM,
    ERROR_NOT_FOUND
};

/**@brief A FIFO instance structure. Keeps track of which bytes to read and write next.
 *        Also it keeps the information about which memory is allocated for the buffer
 *        and its size. This needs to be initialized by app_fifo_init() before use.
 */
typedef struct
{
    uint8_t            p_buf[FIFO_BUF_LEN];           /**< Pointer to FIFO buffer memory.                      */
    uint16_t           buf_size_mask;   /**< Read/write index mask. Also used for size checking. */
    volatile uint32_t  read_pos;        /**< Next read position in the FIFO buffer.              */
    volatile uint32_t  write_pos;       /**< Next write position in the FIFO buffer.             */
} app_fifo_t;

uint32_t fifo_length(app_fifo_t * p_fifo);

/**@brief Function for initializing the FIFO.
 *
 * @param[out] p_fifo   FIFO object.
 * @param[in]  p_buf    FIFO buffer for storing data. The buffer size has to be a power of two.
 * @param[in]  buf_size Size of the FIFO buffer provided, has to be a power of 2.
 *
 * @retval     SUCCESS              If initialization was successful.
 * @retval     ERROR_NULL           If a NULL pointer is provided as buffer.
 * @retval     ERROR_INVALID_LENGTH If size of buffer provided is not a power of two.
 */
//uint32_t app_fifo_init(app_fifo_t * p_fifo, uint8_t * p_buf, uint16_t buf_size);
uint32_t app_fifo_init(app_fifo_t * p_fifo, uint16_t buf_size);

/**@brief Function for adding an element to the FIFO.
 *
 * @param[in]  p_fifo   Pointer to the FIFO.
 * @param[in]  byte     Data byte to add to the FIFO.
 *
 * @retval     SUCCESS              If an element has been successfully added to the FIFO.
 * @retval     ERROR_NO_MEM         If the FIFO is full.
 */
uint32_t app_fifo_put(app_fifo_t * p_fifo, uint8_t byte);

/**@brief Function for getting the next element from the FIFO.
 *
 * @param[in]  p_fifo   Pointer to the FIFO.
 * @param[out] p_byte   Byte fetched from the FIFO.
 *
 * @retval     SUCCESS              If an element was returned.
 * @retval     ERROR_NOT_FOUND      If there is no more elements in the queue.
 */
uint32_t app_fifo_get(app_fifo_t * p_fifo, uint8_t * p_byte);

/**@brief Function for adding multiple element to the FIFO.
 *
 * @param[in]  p_fifo   Pointer to the FIFO.
 * @param[in]  data     Data byte to add to the FIFO.
 * @param[in]  len      data len.
 * @retval     SUCCESS              If an element has been successfully added to the FIFO.
 * @retval     ERROR_NO_MEM         If the FIFO is full.

 */
uint32_t app_fifo_put_multiple(app_fifo_t * p_fifo, uint8_t* data, uint8_t len);

/**@brief Function for getting the multiple element from the FIFO.

 *
 * @param[in]  p_fifo   Pointer to the FIFO.
 * @param[out] data     data fetched from the FIFO.
 * @param[in]  len      data len.
 * @retval     SUCCESS              If an element was returned.
 * @retval     ERROR_NOT_FOUND      If there is no more elements in the queue.
 */
uint32_t app_fifo_get_multiple(app_fifo_t * p_fifo, uint8_t * data, uint8_t len);

/**@brief Function for flushing the FIFO.
 *
 * @param[in]  p_fifo   Pointer to the FIFO.
 *
 * @retval     SUCCESS              If the FIFO flushed successfully.
 */
uint32_t app_fifo_flush(app_fifo_t * p_fifo);

#endif // APP_FIFO_H__

/** @} */

//example.c

app_fifo_t * app_fifo;  

app_fifo = (app_fifo_t *)malloc(sizeof(app_fifo_t));
app_fifo_init(app_fifo, FIFO_BUF_LEN);

app_fifo_put_multiple(app_fifo, (uint8_t*)pcm_data_buf, ret);

int ret = app_fifo_get_multiple(app_fifo, (uint8_t*)buf, 320);

 

1、芯艺设计室

queue.c

/********************************
    队列管理模块
    文件名:queue.c
    编译:WinAVR-20070122

    芯艺设计室 2004-2007  版权所有 
    转载请保留本注释在内的全部内容
    WEB: http://www.chipart.cn
    Email: changfutong@sina.com
*******************************/

#include <stdint.h>

#include "queue.h"

//向队列插入一字节
void QueueInput(PHQUEUE Q,uint8_t dat)
{
    if(Q->data_count < Q->buf_size)
    {
        Q->pBuffer[Q->in_index]=dat;        //写入数据
        Q->in_index=(Q->in_index+1) % (Q->buf_size);//调整入口地址
        Q->data_count++;    //调整数据个数(此操作不可被中断)
    }
    else
    {
        if(Q->error<255)
            Q->error++;
    }
}

//从队列读出一字节
uint8_t QueueOutput(PHQUEUE Q)
{
    uint8_t Ret=0;
    
    if(Q->data_count > 0)
    {
        Ret=Q->pBuffer[Q->out_index];    //读数据
        Q->out_index=(Q->out_index+1) % (Q->buf_size);    //调整出口地址
        Q->data_count--;
    }
    return Ret;
}

//获得队列中数据个数
uint8_t QueueGetDataCount(PHQUEUE Q)
{
    return Q->data_count;
}

//清空队列,执行时不可被中断
void QueueClear(PHQUEUE Q)
{
    Q->in_index=0;
    Q->out_index=0;
    Q->data_count=0;
    Q->error=0;
}

//初始化一队列
void QueueCreate(PHQUEUE Q,uint8_t *buffer,uint8_t buf_size)
{
    Q->pBuffer=buffer;
    Q->buf_size=buf_size;
    QueueClear(Q);
}

queue.h

//queue.h
#ifndef QUEUE_H_
#define QUEUE_H_

//队列数据结构
typedef struct QUEUE_S
{
    uint8_t in_index;//入队地址
    uint8_t out_index;//出队地址
    uint8_t buf_size; //缓冲区长度
    uint8_t *pBuffer;//缓冲
    volatile uint8_t    data_count; //队列内数据个数
    uint8_t error;
}HQUEUE,*PHQUEUE;

void QueueInput(PHQUEUE Q,uint8_t dat);
uint8_t QueueOutput(PHQUEUE Q);
uint8_t QueueGetDataCount(PHQUEUE Q);
void QueueClear(PHQUEUE Q);
void QueueCreate(PHQUEUE Q,uint8_t *buffer,uint8_t buf_size);

#endif

 uart.h

//uart.h
#ifndef UART_H
#define UART_H

void UartInit(void);

uint8_t UartRecv(uint8_t *buf,uint8_t size);

void UartSend(uint8_t *buf,uint8_t size);

#endif

uart.c

/********************************
  基于队列的Mega8 UART通信驱动程序
  文件名:uart.c
  编译:WinAVR-20070122

  硬件:CA-M8X
  时钟:外部4MHz

  芯艺设计室 2004-2007  版权所有 
  转载请保留本注释在内的全部内容
  WEB: http://www.chipart.cn
  Email: changfutong@sina.com
*******************************/
#include <avr/io.h>
#include <avr/interrupt.h>

#include "queue.h"

#define UART_BUF_SIZE 16      //发送和接收缓冲长度

HQUEUE g_SendQueue;  //发送队列句柄
HQUEUE g_RecvQueue;//接收队列句柄

uint8_t g_SendBuffer[UART_BUF_SIZE];//发送缓冲
uint8_t g_RecvBuffer[UART_BUF_SIZE];//接收缓冲

//接收中断SIG_UART_RECV
ISR(USART_RXC_vect )
{
  uint8_t c=UDR; 
  QueueInput(&g_RecvQueue,c);
}

//发送寄存器空中断
ISR (USART_UDRE_vect)
{
  if(QueueGetDataCount(&g_SendQueue)>0)//如果发送缓冲队列不空
  {
    UDR=QueueOutput(&g_SendQueue);  //发送一字节
  }
  else      //否则关闭发送中断
  {
    UCSRB&=~_BV(UDRIE);//关闭数据空中断  
  }
}

////////////以下为本模块三个接口函数///////////////////////////

//初始化
void UartInit(void)
{
  //UART硬件初始化
  UCSRB=0;
  UBRRH=0;
  UBRRL=25;      //9600   4MHz
   UCSRB=(1<<RXCIE)|(1<<RXEN)|(1<<TXEN);
  
  //创建发送/接收队列 
  QueueCreate(&g_SendQueue,g_SendBuffer,UART_BUF_SIZE);
  QueueCreate(&g_RecvQueue,g_RecvBuffer,UART_BUF_SIZE);
}

//读接收缓冲内的数据,buf为读取缓冲,size为buf能接收的最大长度,返回实际接收的长度
uint8_t UartRecv(uint8_t *buf,uint8_t size)
{
  uint8_t i;
  for(i=0;i<size;i++)
  {
    if(QueueGetDataCount(&g_RecvQueue)>0)
    {
      cli();//以下的队列操作不可被中断
      buf[i]=QueueOutput(&g_RecvQueue);
      sei();//中断重新允许
    }
    else
    {
      break;
    }//if else
  }//for
  return i;//返回读到的数据字节数
}

//发送数据 ,buf为发送数据缓冲器,size为要发送的长度
void UartSend(uint8_t *buf,uint8_t size)
{
  uint8_t i;
  
  cli();  //以下的队列操作不可被中断
  
  for(i=0;i<size;i++)
    QueueInput(&g_SendQueue,buf[i]);
  
  sei();  //中断重新允许
  
  UCSRB|=_BV(UDRIE);//数据空中断允许
}
//////////////////////////////////////////////////////////

 

转载于:https://www.cnblogs.com/dong1/p/5982208.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值