高级会员

- 积分
- 836
- 金钱
- 836
- 注册时间
- 2017-6-18
- 在线时间
- 164 小时
|
发表于 2017-8-11 15:49:30
|
显示全部楼层
/*
serial.c - 低级功能用于通过串行端口发送和接收字节
Grbl的一部分
*/
#include "avr/io.h"
#include <avr/interrupt.h>
#include "serial.h"
#include "config.h"
#include "motion_control.h"
#include "protocol.h"
uint8_t rx_buffer[RX_BUFFER_SIZE];
uint8_t rx_buffer_head = 0;
uint8_t rx_buffer_tail = 0;
uint8_t tx_buffer[TX_BUFFER_SIZE];
uint8_t tx_buffer_head = 0;
volatile uint8_t tx_buffer_tail = 0;
/**************************************************************************************************/
#ifdef ENABLE_XONXOFF //默认 ENABLE_XONXOFF = 0; 内部将不进行编译
volatile uint8_t flow_ctrl = XON_SENT; //流控制状态变量
/*************************************************/
//***RX缓冲区 字节返回 函数***//
static uint8_t get_rx_buffer_count(void)
{
if (rx_buffer_head == rx_buffer_tail) { return(0); } //头 = 尾, 返回 0;
if (rx_buffer_head < rx_buffer_tail) { return(rx_buffer_tail-rx_buffer_head); } //头 < 尾, 返回 尾 - 头
return (RX_BUFFER_SIZE - (rx_buffer_head-rx_buffer_tail)); //头 > 尾, 返回 头 - 尾
}
#endif
/**************************************************************************************************/
//***串口 初始化***// //默认为8位,无奇偶校验,1位停止位
void serial_init(void)
{
//设置波特率
#if BAUD_RATE < 57600
uint16_t UBRR0_value = ((F_CPU / (8L * BAUD_RATE)) - 1)/2;
UCSR0A &= ~(1 << U2X0); // 波特率倍频器关 - 仅在Uno XXX上需要
#else
uint16_t UBRR0_value = ((F_CPU / (4L * BAUD_RATE)) - 1)/2;
UCSR0A |= (1 << U2X0); //波特率为高波特率,即115200
#endif
UBRR0H = UBRR0_value >> 8;UBRR0L = UBRR0_value;
UCSR0B |= 1<<4; //RXEN0 = 1; 接收使能
UCSR0B |= 1<<3; //TXEN0 = 1; 发送使能
UCSR0B |= 1<<7; //RXCIE0 = 1; 接收结束中断使能
UCSR0C |= 3<<1; //UCSZ0 = 3(11); 8bit数据模式
}
/**************************************************************************************************/
//***串口 发送***//
void serial_write(uint8_t data)
{
uint8_t next_head = tx_buffer_head + 1; //把tx_buffer_head 加1后放入 next_head 临时头指针
if (next_head == TX_BUFFER_SIZE){next_head = 0;} //next_head 循环流结构
while (next_head == tx_buffer_tail) //由于 next_head = txbuffer_head +1; 所以只有 在缓冲区中的数未发完时, 才有可能等于tx_buffer_tail, 故等待缓冲区空了才能发;
{
if (sys.execute & EXEC_RESET) return; //如果sys 变量中有 RESET 标志,直接跳出,响应复位;
}
tx_buffer[tx_buffer_head] = data; //数据 放入 tx_buffer 缓冲流
tx_buffer_head = next_head; //更新 tx_buffer_head 头指针位置
UCSR0B |= (1 << UDRIE0); //使能数据寄存器空中断, 让发送缓冲区 TX流 自动发送;
}
/**************************************************************************************************/
//***数据寄存器空 中断***//
#if defined(__AVR_ATmega644P__) || defined(__AVR_ATmega2560__)
ISR(USART0_UDRE_vect)
#else
ISR(USART_UDRE_vect)
#endif
{
uint8_t tail = tx_buffer_tail; //TX流 临时尾指针
#ifdef ENABLE_XONXOFF //默认 ENABLE_XONXOFF = 0; 内部将不进行编译
if (flow_ctrl == SEND_XOFF)
{
UDR0 = XOFF_CHAR;
flow_ctrl = XOFF_SENT;
}
else if (flow_ctrl == SEND_XON)
{
UDR0 = XON_CHAR;
flow_ctrl = XON_SENT;
}
else
#endif
{
UDR0 = tx_buffer[tail]; //从缓冲区发送一个字节
tail++; //更新尾部位置
if (tail == TX_BUFFER_SIZE){tail = 0;} //TX流尾指针循环流
tx_buffer_tail = tail; //TX流尾指针写入tx_buffer_tail;
}
if (tail == tx_buffer_head){UCSR0B &= ~(1 << UDRIE0);} //如果结束传输,关闭数据寄存器空中断停止tx流, 注: 此时tx_buffer_head = tx_buffer_tail;
}
/*---------------------------------------------------------------------------------------------------------------------------------*/
//***串口 接收***//
uint8_t serial_read(void)
{
// if(seral_Enable_FLAG)
// { return SERIAL_NO_DATA; }
// else
// {
if (rx_buffer_head == rx_buffer_tail){return SERIAL_NO_DATA;} //RX_头=尾; 跳出返回没有收到数据
else
{
uint8_t data = rx_buffer[rx_buffer_tail]; //从rx_buffer 缓冲区中获取数据
rx_buffer_tail++;
if (rx_buffer_tail == RX_BUFFER_SIZE) rx_buffer_tail = 0; //rx_buffer_tail 尾指针循环流
#ifdef ENABLE_XONXOFF //默认 ENABLE_XONXOFF = 0; 内部将不进行编译
if ((get_rx_buffer_count() < RX_BUFFER_LOW) && flow_ctrl == XOFF_SENT)
{
flow_ctrl = SEND_XON;
UCSR0B |= (1 << UDRIE0); // Force TX
}
#endif
return data;
}
// }
}
/**************************************************************************************************/
//***串口 接收中断***//
#if defined(__AVR_ATmega644P__) || defined(__AVR_ATmega2560__)
ISR(USART0_RX_vect)
#else
ISR(USART_RX_vect)
#endif
{
uint8_t data = UDR0; //从 串口0 数据寄存器 取出数据, 放入data;
uint8_t next_head;
switch (data) //直接从串行流中取出运行时命令字符。 这些字符不会传入缓冲区,但是这些字符串用于运行时执行。
{
case CMD_STATUS_REPORT: sys.execute |= EXEC_STATUS_REPORT; break; //设为true
case CMD_CYCLE_START: sys.execute |= EXEC_CYCLE_START; break; //设为true
case CMD_FEED_HOLD: sys.execute |= EXEC_FEED_HOLD; break; //设为true
case CMD_RESET: mc_reset(); break; //调用运动控制复位程序。
default: //将字符写入缓冲区
{
next_head = rx_buffer_head + 1;
if (next_head == RX_BUFFER_SIZE){next_head = 0;} //next_head 指针循环结构
if (next_head != rx_buffer_tail) //如果数据rx_buffer缓冲区满,将不写入缓冲区 //rx_buffer_head 头部指针也不会动
{
rx_buffer[rx_buffer_head] = data;
rx_buffer_head = next_head;
#ifdef ENABLE_XONXOFF //默认 ENABLE_XONXOFF = 0; 内部将不进行编译
if ((get_rx_buffer_count() >= RX_BUFFER_FULL) && flow_ctrl == XON_SENT)
{
flow_ctrl = SEND_XOFF;
UCSR0B |= (1 << UDRIE0); //强制TX
}
#endif
}
}
}
}
/**************************************************************************************************/
//***重置 读串口缓冲区指针***//
void serial_reset_read_buffer(void)
{
rx_buffer_tail = rx_buffer_head; //尾 = 头的当前位置
#ifdef ENABLE_XONXOFF //默认 ENABLE_XONXOFF = 0; 内部将不进行编译
flow_ctrl = XON_SENT;
#endif
}
/**************************************************************************************************/
|
|