TA的每日心情 | 奋斗 2022-4-7 16:37 |
---|
签到天数: 736 天 连续签到: 1 天 [LV.9]以坛为家II
|
感谢爱板网提供一款基于AVR微控制器的Atmel Xplained系列的mini评估板——ATmega328P-XMINI,确实很迷你——尺寸75mm*60mm。
一、测试准备:1、Atmel studio IDE软件;2、mini-USB线缆;3、Atmel Mega328 Xplained mini Demo板
二、测试步骤
1、从ATMEL官网上把Atmel Studio6.2下载下来,注意下载10月份最新更新的版本,否则会出现各种意想不到的BUG,比如IDE总是莫名其妙的弹出去。将安装文件下载到本地进行安装,安装基本上是分为4个步骤:.NET framework 4.0、VS2010、ATMEL的usb驱动和IDE软件。整个过程只需一路NEXT就行,安装前先关掉类似360安全卫士的软件,否则安装过程中总是弹出各种拦截对话框。
2、安装完成后,打开Atmel studio IDE软件,用mini-USB线缆插上ATmega328P-XMINI,另一端插上电脑的USB接口,电脑会自动识别EDBG接口。EDBG是Atmel特有的板载调试器,不仅省去了外部调试工具,而且生成虚拟串口可以用于与主机通信。
**********************************************************************************************************************************************************************************
注意:通过mini-USB线连接电脑的USB接口和ATmega328P-XMINI时,可能会出现mEDBG无法识别的现象。原因可能涉及以下几种:
- 1、操作系统原因——精简版的GOST系统(尤其是XP的系统),缺少必要的usbser.sys文件;解决办法:从网上下下来解压后将usbser.sys复制到c:\windows\system32\drivers;有些系统可能缺少大量的*.dll文件,建议直接重装系统。(笔者直接重装了!)
- 2、USB接口原因——某些台式机USB接口年久出现故障,无法识别mEDBG,可多换几个USB接口试试(笔者换了3个才成功!说多了都是泪。。。)
- 3、手贱upgrade原因——有的人一打开Atmel studio IDE就有提示要升级,手贱点了升级,半天没反应,强行中止了,直接导致板子无法识别。这个时候,打开Atmel studio IDE,选择tools→command prompt,输入指令atfw –t edbg –a “D:\Program Files\Atmel\Atmel Studio 6.2\tools\EDBG\edbg_fw.zip”
**********************************************************************************************************************************************************************************
3、上电的同时Atmel studio IDE很快会识别出这块ATmega328P-XMINI,并且会展现出ATmega328P-XMINI评估板的相关信息和帮助文件。
4、Demo程序
ATmega328P-XMINI评估板预置了Demo程序,这个程序很有意思,并不是简单的按键点亮LED功能。而是一个morse编解码的程序,可以通过串口程序窗口互动。程序在初始化时会发送ATMEL五个字符的morse码。
该Demo能把串口输入的字符解码为morse编码来驱动LED亮和灭,同时我们按下评估板的按键动作也可以解码为字符在串口程序显示。这样可以将ATmega328P-XMINI评估板当作一款小型的morse码发报机来用!
但是一次不能发送过多字符,否则解码过慢显示不全,比如输入eeboard,结果只显示了EEBD
下面是通过按键发送morse码,程序会解码为字符在串口程序显示,同时LED灯会根据morse码的点横会短亮或长亮。
附上morse源码程序,这个是历经千辛万苦”翻到的“,具体过程就不详述了。。。
/** * \file remorse.c * * \brief Morse Code Encoder/Decorder board support package * * Copyright (c) 2011 - 2014 Atmel Corporation. All rights reserved. * * \asf_license_start * * \page License * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. 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. * * 3. The name of Atmel may not be used to endorse or promote products derived * from this software without specific prior written permission. * * 4. This software may only be redistributed and used in connection with an * Atmel microcontroller product. * * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. * * \asf_license_stop * * This version of Remorse is a polling implemenation, and implemented * as only one self contained file. */#define F_CPU 16000000UL // Fuse for internal oscillator at 16MHz#include <stddef.h>#include <ctype.h>#include <stdbool.h>#include <stdio.h>#include <string.h>#include <avr/io.h>#include <avr/interrupt.h>#include <util/delay.h>#include <avr/pgmspace.h>/* typedefs */typedef struct /* RING - ring buffer */ { int p_to_buf; /* offset from start of buffer where to write next */ int p_from_buf; /* offset from start of buffer where to read next */ int buf_size; /* size of ring in bytes */ char * buf; /* pointer to start of buffer */ } RING;typedef RING *RING_ID;/* defines */#define DOT_TIME_IN_TICKS (25) #define DOT_TIME_IN_MS (DOT_TIME_IN_TICKS * 10.0) #define LED_ON PORTB |= (1<<ORTB5)#define LED_OFF PORTB &= ~(1<<ORTB5)#define USART_BAUDRATE 9600#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)#define REMORSE_CLK_HZ (100) // the clock basis for polling and sequencing#define REMORSE_TIMEOUT (1000) // remorse will restart after this many idle ticks#define REMORSE_RESTART (400) // remorse will restart if button held this long#define MORSE_RX_BUF_SIZE (32) // ring buffer for decoded morse code/* macros */#define min(a,b) \ ({ __typeof__ (a) _a = (a); \ __typeof__ (b) _b = (b); \ _a < _b ? _a : _b; })/* locals */static char morse_rx_buf[MORSE_RX_BUF_SIZE + 1]; // buffer for morse characters readstatic RING morse_rx_ring; // morse receive buffer ringstatic RING_ID morse_rx_ring_id; // morse receive buffer ring idstatic bool user_input = false; // Instructions print out until first character receivedstatic volatile uint32_t remorse_tick_cnt; // incremented on each clock tickstatic volatile uint32_t remorse_wd_cnt; // reset to zero after each user input outputstatic volatile bool remorse_restart; // set by watchdog to true to restart applicationconst uint8_t morse_ascii_tbl[][2] = { // Morse Hex A M Morse Code Binary ASCII Notes {6, 0x14}, // ! ! – · – · – – 010100 33 33 Exclamation mark [!] {6, 0x2D}, // " " · – · · – · 101101 34 34 Quotation mark ["] {8, 0xFF}, // # ERR · · · · · · · · 11111111 35 ERR Hash mark [#] {7, 0x76}, // $ $ · · · – · · – 1110110 36 36 Dollar sign [$] {8, 0xFF}, // % ERR · · · · · · · · 11111111 37 ERR Percent [%] {5, 0x17}, // & & · – · · · 10111 38 38 Ampersand [&], Wait {6, 0x21}, // ' ' · – – – – · 100001 39 39 Apostrophe ['] {5, 0x09}, // ( ( – · – – · 01001 40 40 Parenthesis open [(] {6, 0x12}, // ) ) – · – – · – 010010 41 41 Parenthesis close [)] {8, 0xFF}, // * ERR · · · · · · · · 11111111 42 69 Asterix
{5, 0x15}, // + + · – · – · 10101 43 43 Plus [+] {6, 0x0C}, // , , – – · · – – 001100 44 44 Comma [,] {6, 0x1E}, // - - – · · · · – 011110 45 45 Hyphen, Minus [-] {6, 0x2A}, // . . · – · – · – 101010 46 46 Period [.] {5, 0x0D}, // / / – · · – · 01101 47 47 Slash [/], Fraction bar {5, 0x00}, // 0 0 – – – – – 00000 48 48 {5, 0x10}, // 1 1 · – – – – 10000 49 49 {5, 0x18}, // 2 2 · · – – – 11000 50 50 {5, 0x1C}, // 3 3 · · · – – 11100 51 51 {5, 0x1E}, // 4 4 · · · · – 11110 52 52 {5, 0x1F}, // 5 5 · · · · · 11111 53 53 {5, 0x0F}, // 6 6 – · · · · 01111 54 54 {5, 0x07}, // 7 7 – – · · · 00111 55 55 {5, 0x03}, // 8 8 – – – · · 00011 56 56 {5, 0x01}, // 9 9 – – – – · 00001 57 57 {6, 0x07}, // : : – – – · · · 000111 58 58 Colon [:] {6, 0x15}, // ; ; – · – · – · 010101 59 59 Semicolon [;] {8, 0xFF}, // < ERR · · · · · · · · 11111111 60 ERR Less Than [<] {5, 0x0E}, // = = – · · · – 01110 61 61 Double dash [=] {8, 0xFF}, // > ERR · · · · · · · · 11111111 62 ERR Greather Than [<] {6, 0x33}, // ? ? · · – – · · 110011 63 63 Question mark [?] {6, 0x25}, // @ @ · – – · – · 100101 64 64 At sign [@] {2, 0x02}, // A A · – 10 65 65 {4, 0x07}, // B B – · · · 0111 66 66 {4, 0x05}, // C C – · – · 0101 67 67 {3, 0x03}, // D D – · · 011 68 68 {1, 0x01}, // E E · 1 69 69 {4, 0x0D}, // F F · · – · 1101 70 70 {3, 0x01}, // G G – – · 001 71 71 {4, 0x0F}, // H H · · · · 1111 72 72 {2, 0x03}, // I I · · 11 73 73 {4, 0x08}, // J J · – – – 1000 74 74 {3, 0x02}, // K K – · – 010 75 75 {4, 0x0B}, // L L · – · · 1011 76 76 {2, 0x00}, // M M – – 00 77 77 {2, 0x01}, // N N – · 01 78 78 {3, 0x00}, // O O – – – 000 79 79 {4, 0x09}, // P P · – – · 1001 80 80 {4, 0x02}, // Q Q – – · – 0010 81 81 {3, 0x05}, // R R · – · 101 82 82 {3, 0x07}, // S S · · · 111 83 83 {1, 0x00}, // T T – 0 84 84 {3, 0x06}, // U U · · – 110 85 85 {4, 0x0E}, // V V · · · – 1110 86 86 {3, 0x04}, // W W · – – 100 87 87 {4, 0x06}, // X X – · · – 0110 88 88 {4, 0x04}, // Y Y – · – – 0100 89 89 {4, 0x03}, // Z Z – – · · 0011 90 90 {8, 0xFF}, // [ ERR · · · · · · · · 11111111 91 ERR Open Bracket [[] {8, 0xFF}, // \ ERR · · · · · · · · 11111111 92 ERR Backslash [\] {8, 0xFF}, // ] ERR · · · · · · · · 11111111 93 ERR Close Bracket []] {8, 0xFF}, // ^ ERR · · · · · · · · 11111111 94 ERR Circumflex [^] {6, 0x32} // _ _ · · – – · – 110010 95 95 Underscore [_] };/* forward declarations */static int bsp_tty_putchar (char c, FILE *stream);static int bsp_tty_getchar (FILE *stream);static int bsp_morse_putchar (char c, FILE *stream);static int bsp_morse_getchar (FILE *stream);static void remorse_instructions(void);static void morse_fmtchar (char rc);static void morse_poll (void);static RING_ID rng_init (RING *p_ring, int nbytes, char *buffer);static bool rng_is_empty (RING_ID ring_id);static bool rng_is_full (RING_ID ring_id);static int rng_buf_get (RING_ID rng_id, char *buffer, int maxbytes);static int rng_buf_put (RING_ID rng_id, char *buffer, int nbytes);static int rng_free_bytes (RING_ID ring_id);static int rng_nBytes (RING_ID ring_id);static void rng_flush (RING_ID ring_id);// Associate the devices with AVR libc FILE streams to enable standard i/o callsstatic FILE tty_console = FDEV_SETUP_STREAM(bsp_tty_putchar, bsp_tty_getchar, _FDEV_SETUP_RW);static FILE tty_morse = FDEV_SETUP_STREAM(bsp_morse_putchar, bsp_morse_getchar, _FDEV_SETUP_RW);/** * \brief Entry point for morse code example * */int main (void) { char rc; /* set up the IO pins */ DDRB |= (1<<DDB5); // PB5 As Output pin PORTB |= (1<<DDB5); // PB5 Activate internal pullUp resistor DDRB &= ~(1<<DDB7); // PB1 As Input pin PORTB |= 1<<DDB7; // PB1 Activate internal pullUp resistor LED_OFF; // start with the LED off UCSR0B = (1 << RXEN0) | (1 << TXEN0); // turn on the transmission and reception circuitry UCSR0C = (1 << UCSZ00) | (1 << UCSZ01); // use 8-bit character sizes UBRR0H = (BAUD_PRESCALE >> 8); // upper 8-bits of baud rate value into high byte of UBRR register UBRR0L = BAUD_PRESCALE; // lower 8-bits of baud rate value into low byte of UBRR register /* set up the system 100Hz timer */ OCR1A = 20000; // Set CTC compare value to 10ms @ 8Mhz Clock (Mode 4) TCCR1B |= (1 << WGM12); // Configure timer 1 for CTC mode (Mode 4) TIMSK1 |= (1 << OCIE1A); // Enable interrupt on compare match TCCR1B |= (1 << CS11); // set prescaler to 8 and starts the timer /* initialize ring buffers */ morse_rx_ring_id = rng_init (&morse_rx_ring, MORSE_RX_BUF_SIZE, morse_rx_buf); /* Enable global interrupts */ sei(); /* attach the serial port to stdio streams */ stdout = &tty_console; stdin = &tty_console; stderr = &tty_console; /* encode/decode the user input to/from morse code */ for (;;) // loop forever (timeouts restart here) { remorse_instructions (); // print out some instructions remorse_restart = false; // reset watchdog remorse_wd_cnt = 0; // reinitialize watchdog timer while (!remorse_restart) // check watchdog { rc = getchar (); // non-blocking in this application /* process input from serial line */ if (!ferror(stdin)) // was a character available? { remorse_wd_cnt = 0; // reinitialize watchdog timer morse_fmtchar (rc); // echo the morse code on console fputc (rc, &tty_morse); // encode the character to morse led } else { clearerr (&tty_console); // no input, clear error } /* process input from morse decoder */ rc = fgetc (&tty_morse); if (!ferror(&tty_morse)) // was a morse character available? { remorse_wd_cnt = 0; // reinitialize watchdog timer putchar (rc); // print the character to console } else { clearerr (&tty_morse); // no input, clear error } } } /* we should never get here */ return (0); }/** * \brief Push a character out uart transmitter * * Polling version of character write. We spin here until character * can be placed in transmit register. */static int bsp_tty_putchar(char c, FILE *stream) { if (c == '\n') // handle linefeed - carriage return bsp_tty_putchar('\r', stream); while ((UCSR0A & (1 << UDRE0)) == 0) { // Do nothing until UDR is ready for more data to be written to it }; UDR0 = c; // transmit character return (0); // transmit success }/** * \brief Fetch a character from uart receiver * * Polling version of a character read. We spin here until receive * buffer has something to read. */static int bsp_tty_getchar(FILE *stream) { if ((UCSR0A & (1 << RXC0)) == 0) return (_FDEV_ERR); // No character available, so we return error user_input = true; // Record the fact that we have received input return (UDR0); // Return the received character }/** * \brief Flash out morse code for character on led * * Polling version of character write. We spin here until character * can be placed in transmit register. */static int bsp_morse_putchar(char c, FILE *stream) { int index = toupper(c) - '!'; if (c == ' ') { // Delay between words is seven units LED_OFF; // LED OFF between words _delay_ms (7 * DOT_TIME_IN_MS); } else if ((index >= 0) && (index < (sizeof (morse_ascii_tbl) / 2))) { unsigned int mask = (0x1 << (morse_ascii_tbl[index][0] - 1)); while (mask != 0) { if (morse_ascii_tbl[index][1] & mask) { // DIT LED_ON; // Start DIT LED on _delay_ms (DOT_TIME_IN_MS); // DIT length is one unit } else { // DASH LED_ON; // Start DASH LED on _delay_ms (3 * DOT_TIME_IN_MS); // DASH length is three units } LED_OFF; // DIT or DASH is finished // Delay between parts of same letter is one unit _delay_ms (DOT_TIME_IN_MS); mask = mask >> 1; } // Delay between letters is three units (two more) _delay_ms (2 * DOT_TIME_IN_MS); } return (0); // transmit success }/** * \brief Decode morse code input from button * * If we have any decoded morse code we return it or _FDEV_ERR if none. */static int bsp_morse_getchar(FILE *stream) { char morse_char; if (rng_buf_get (morse_rx_ring_id, &morse_char, 1) == 1) return (morse_char); // return next character return (_FDEV_ERR); // No character available, so we return error }/** * \brief Print out character as ASCII morse code (. and -) */static void morse_fmtchar (char rc) { int index = toupper(rc) - '!'; if ((index >= 0) && (index < (sizeof (morse_ascii_tbl) / 2))) { unsigned int mask = (0x1 << (morse_ascii_tbl[index][0] - 1)); while (mask != 0) { printf_P (PSTR(" %c"), (morse_ascii_tbl[index][1] & mask) ? '.' : '-'); mask = mask >> 1; } printf_P (PSTR(" [%c]"), toupper(rc)); } else { /* handle non-printable characters */ if (rc == '\r') printf_P (PSTR(" . - . - [<CR>]\n-> ")); } }/** * \brief Parse morse code pattern into ASCII character * * \param[in] pattern morse code pattern to match * \param[in] len morse code patter length * \return the ASCII character that matches the mores code patter */static char morse_parse (uint8_t pattern, int len) { int index; for (index = 0; index < (sizeof (morse_ascii_tbl) / 2); index ++) { if ((morse_ascii_tbl[index][0] == len) && (morse_ascii_tbl[index][1] == pattern)) return (index + '!'); } /* pattern not found! */ return ('*'); // return asterix as error indicator (not a morse character) }/** * \brief Print out remorse instructions */static void remorse_instructions (void) { if (!user_input) { printf_P (PSTR("\n")); printf_P (PSTR("Morse Encoder/Decoder\n")); printf_P (PSTR("Copyright (c) 2011 - 2014 Atmel Corporation. All rights reserved.\n")); printf_P (PSTR("\n")); printf_P (PSTR("Characters received from the serial port will be be echoed back in morse code.\n")); printf_P (PSTR("Morse code tapped into button will be converted to ASCII.\n")); printf_P (PSTR("\n")); printf_P (PSTR("(ie)")); morse_fmtchar ('A'); fputc ('A', &tty_morse); morse_fmtchar ('T'); fputc ('T', &tty_morse); morse_fmtchar ('M'); fputc ('M', &tty_morse); morse_fmtchar ('E'); fputc ('E', &tty_morse); morse_fmtchar ('L'); fputc ('L', &tty_morse); } printf_P (PSTR("\n-> ")); // prompt for serial input }/** * Interrupt Service Routines *//** * \brief Remorse clock interrupt routine * * This routine is called at interrupt level on each clock interrupt. */ISR(TIMER1_COMPA_vect) { ++remorse_tick_cnt; // always advance remorse tick count if (++remorse_wd_cnt > REMORSE_TIMEOUT) // fire watchdog on timeout remorse_restart = true; morse_poll (); // poll for morse input }/** * \brief Poll button for debounced conversion to Morse code */static void morse_poll (void) { static uint8_t morse_code = 0; // built up morse code input static uint8_t morse_code_len = 0; // morse code length static uint8_t button_hist = 0; // 8 sample button history static bool button_down = false; // current state of button static uint32_t tick_down = 0; // tick when button released static uint32_t tick_up = 0; // tick when button pressed static uint32_t duration = 0; // ticks with button down static uint32_t space = 0; // ticks with button up /* shift in the current state of the button */ button_hist = (button_hist<<1) | !(PINB & (1<<B7)) | 0xf0; if (button_hist == 0xff) // all samples are button down { LED_ON; // light the LED for user feedback user_input = true; // we have interaction if (!button_down) // are we changing state? { button_down = true; // set debounced button state tick_down = remorse_tick_cnt; // timestamp the button press } duration = remorse_tick_cnt - tick_down; if (duration > REMORSE_RESTART) // restart! { morse_code_len = 0; // erase current code morse_code = 0; // erase last code rng_flush (morse_rx_ring_id); // flush the morse input ring user_input = false; // start from begining remorse_restart = true; // RESTART REMORSE } } else if (button_hist == 0xf0) // all samples are button up { if (button_down) // are we changing state? { LED_OFF; // turn off LED between morse keys button_down = false; // set debounced button state tick_up = remorse_tick_cnt; // timestamp button release /* emit the right code based on click duration */ duration = tick_up - tick_down; if (duration <= (2 * DOT_TIME_IN_TICKS)) // dot { morse_code = (morse_code << 1) | 1; morse_code_len++; rng_buf_put (morse_rx_ring_id, " .", 2); } else if (duration <= (5 * DOT_TIME_IN_TICKS)) // dash { morse_code = (morse_code << 1) | 0; morse_code_len++; rng_buf_put (morse_rx_ring_id, " -", 2); } } } /* return now if there has been no input or button is currently down */ if ((!user_input) || (button_down)) return; /* now process spaces between button presses as follows * - one dot time between code (NOP) * - three dot time between letters (flush the letter) * - seven dot time between words (flush space chracter) */ space = remorse_tick_cnt - tick_up; if (space == (4 * DOT_TIME_IN_TICKS)) // this will only happen once { char morse_char = morse_parse (morse_code, morse_code_len); // letter seperator rng_buf_put (morse_rx_ring_id, " [", 2); rng_buf_put (morse_rx_ring_id, &morse_char, 1); rng_buf_put (morse_rx_ring_id, "]", 1); morse_code_len = 0; // get ready for next letter morse_code = 0; // erase last code } else if (space == (10 * DOT_TIME_IN_TICKS)) // this will only happen once { // word separator rng_buf_put (morse_rx_ring_id, " [ ]", 4); } }/** * Ring Utility Functions *//** * \brief initialize an empty ring buffer * * This routine initializes a ring buffer of size "nbytes". The * buffer must be one byte larger than nBytes since the algorithm * always leaves at least one empty byte in the buffer. * * \param[in] p_ring pointer to a RING struct * \param[in] nbytes number of bytes in ring buffer * \param[in] buffer pointer to RING buffer of size nBytes + 1 * \return ID of the ring buffer, or NULL if init fails */RING_ID rng_init (RING * p_ring, int nbytes, char *buffer) { RING_ID ring_id = p_ring; /* RING_ID is simply a pointer to RING */ /* bump number of bytes requested because ring buffer algorithm * always leaves at least one empty byte in buffer */ ring_id->buf_size = nbytes + 1; ring_id->buf = buffer; rng_flush (ring_id); return (ring_id); }/** * \brief make a ring buffer empty * * This routine initializes a specified ring buffer to be empty. * Any data currently in the buffer will be lost. * * \param[in] ring_id ring buffer to initialize */void rng_flush (RING_ID ring_id) { ring_id->p_to_buf = 0; ring_id->p_from_buf = 0; }/** * \brief - get characters from a ring buffer * * This routine copies bytes from the ring buffer <rng_id> into <buffer>. * It copies as many bytes as are available in the ring, up to <maxbytes>. * The bytes copied will be removed from the ring. * * param[in] ring_id ring buffer to get data from * param[in] buffer pointer to buffer to receive data * param[in] maxbytes maximum number of bytes to get * \return The number of bytes actually received from the ring buffer; * it may be zero if the ring buffer is empty at the time of the call. */int rng_buf_get (RING_ID rng_id, char *buffer, int maxbytes) { int bytesgot = 0; int p_to_buf = rng_id->p_to_buf; int bytes2; int p_rng_tmp = 0; if (p_to_buf >= rng_id->p_from_buf) { /* p_to_buf has not wrapped around */ bytesgot = min (maxbytes, p_to_buf - rng_id->p_from_buf); memcpy (buffer, &rng_id->buf [rng_id->p_from_buf], bytesgot); rng_id->p_from_buf += bytesgot; } else { /* p_to_buf has wrapped around. Grab chars up to the end of the * buffer, then wrap around if we need to. */ bytesgot = min (maxbytes, rng_id->buf_size - rng_id->p_from_buf); memcpy (buffer, &rng_id->buf [rng_id->p_from_buf], bytesgot); p_rng_tmp = rng_id->p_from_buf + bytesgot; /* If p_from_buf is equal to buf_size, we've read the entire buffer, * and need to wrap now. If bytesgot < maxbytes, copy some more chars * in now. */ if (p_rng_tmp == rng_id->buf_size) { bytes2 = min (maxbytes - bytesgot, p_to_buf); memcpy (buffer + bytesgot, rng_id->buf, bytes2); rng_id->p_from_buf = bytes2; bytesgot += bytes2; } else rng_id->p_from_buf = p_rng_tmp; } return (bytesgot); }/** * \brief - put bytes into a ring buffer * * This routine puts bytes from <buffer> into ring buffer <ring_id>. The * specified number of bytes will be put into the ring, up to the number of * bytes available in the ring. * * * \param[in] rng_id ring buffer to put data into * \param[in] buffer buffer to get data from * \param[in] nbytes number of bytes to try to put * \return The number of bytes actually put into the ring buffer; * it may be less than number requested, even zero, * if there is insufficient room in the ring buffer at the time of the call. */int rng_buf_put (RING_ID rng_id, char *buffer, int nbytes) { int bytesput = 0; int p_from_buf = rng_id->p_from_buf; int bytes2; int p_rng_tmp = 0; if (p_from_buf > rng_id->p_to_buf) { /* p_from_buf is ahead of p_to_buf. We can fill up to two bytes * before it */ bytesput = min (nbytes, p_from_buf - rng_id->p_to_buf - 1); memcpy (&rng_id->buf [rng_id->p_to_buf], buffer, bytesput); rng_id->p_to_buf += bytesput; } else if (p_from_buf == 0) { /* p_from_buf is at the beginning of the buffer. We can fill till * the next-to-last element */ bytesput = min (nbytes, rng_id->buf_size - rng_id->p_to_buf - 1); memcpy (&rng_id->buf [rng_id->p_to_buf], buffer, bytesput); rng_id->p_to_buf += bytesput; } else { /* p_from_buf has wrapped around, and its not 0, so we can fill * at least to the end of the ring buffer. Do so, then see if * we need to wrap and put more at the beginning of the buffer. */ bytesput = min (nbytes, rng_id->buf_size - rng_id->p_to_buf); memcpy (&rng_id->buf [rng_id->p_to_buf], buffer, bytesput); p_rng_tmp = rng_id->p_to_buf + bytesput; if (p_rng_tmp == rng_id->buf_size) { /* We need to wrap, and perhaps put some more chars */ bytes2 = min (nbytes - bytesput, p_from_buf - 1); memcpy (rng_id->buf, buffer + bytesput, bytes2); rng_id->p_to_buf = bytes2; bytesput += bytes2; } else rng_id->p_to_buf = p_rng_tmp; } return (bytesput); }/** * \brief - test if a ring buffer is empty * * This routine determines if a specified ring buffer is empty. * * \param[in] rng_id ring buffer to test * \return TRUE if empty, FALSE if not. */bool rng_is_empty (RING_ID ring_id) { return (ring_id->p_to_buf == ring_id->p_from_buf); }/** * \brief - test if a ring buffer is full (no more room) * * This routine determines if a specified ring buffer is completely full. * * \param[in] rng_id ring buffer to test * \return TRUE if full, FALSE if not. */bool rng_is_full (RING_ID ring_id) { int n = ring_id->p_to_buf - ring_id->p_from_buf + 1; return ((n == 0) || (n == ring_id->buf_size)); }/** * \brief - determine the number of free bytes in a ring buffer * * This routine determines the number of bytes currently unused in a specified * ring buffer. * * \param[in] rng_id ring buffer to examine * \return The number of unused bytes in the ring buffer. */int rng_free_bytes (RING_ID ring_id) { int n = ring_id->p_from_buf - ring_id->p_to_buf - 1; if (n < 0) n += ring_id->buf_size; return (n); }/** * * rng_nBytes - determine the number of bytes in a ring buffer * * This routine determines the number of bytes currently in a specified * ring buffer. * * \param[in] rng_id ring buffer to be enumerated * \return The number of bytes filled in the ring buffer. */int rng_nBytes (RING_ID ring_id) { int n = ring_id->p_to_buf - ring_id->p_from_buf; if (n < 0) n += ring_id->buf_size; return (n); }/** * \brief - put a byte ahead in a ring buffer without moving ring pointers * * This routine writes a byte into the ring, but does not move the ring buffer * pointers. Thus the byte will not yet be available to rng_buf_get() calls. * The byte is written <offset> bytes ahead of the next input location in the * ring. Thus, an offset of 0 puts the byte in the same position as would * RNG_ELEM_PUT would put a byte, except that the input pointer is not updated. * * Bytes written ahead in the ring buffer with this routine can be made available * all at once by subsequently moving the ring buffer pointers with the routine * rng_move_ahead(). * * Before calling nng_put_ahead(), the caller must verify that at least * <offset> + 1 bytes are available in the ring buffer. * * \param[in] ring_id ring buffer to put byte in * \param[in] byte byte to be put in ring * \param[in] offset offset beyond next input byte where to put byte */void rng_put_ahead (RING_ID ring_id, char byte, int offset) { int n = ring_id->p_to_buf + offset; if (n >= ring_id->buf_size) n -= ring_id->buf_size; *(ring_id->buf + n) = byte; }/** * \brief - advance a ring pointer by <n> bytes * * This routine advances the ring buffer input pointer by <n> bytes. This makes * <n> bytes available in the ring buffer, after having been written ahead in * the ring buffer with rng_put_ahead(). * * \param[in] ring_id ring buffer to be advanced * \param[in] n number of bytes ahead to move input pointer */void rng_move_ahead (RING_ID ring_id, int n) { n += ring_id->p_to_buf; if (n >= ring_id->buf_size) n -= ring_id->buf_size; ring_id->p_to_buf = n; }有精力的同学可以找我要完整代码,这个只是remorse.c文件。 |
|