GRBL八:STM32程式碼移植——串列埠
阿新 • • 發佈:2019-01-30
串列埠部分的一直只需要修改底層的串列埠程式碼就好包括串列埠初始化,讀寫函式,中斷服務函式
serial.c
/* serial.c - Low level functions for sending and recieving bytes via the serial port Part of Grbl The MIT License (MIT) GRBL(tm) - Embedded CNC g-code interpreter and motion-controller Copyright (c) 2009-2011 Simen Svale Skogsrud Copyright (c) 2011-2012 Sungeun K. Jeon Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include <stm32f10x_lib.h> //#include "stm32f10x.h" #include "serial.h" #include "config.h" #include "motion_control.h" #include "protocol.h" uint8_t serial_rx_buffer[RX_BUFFER_SIZE]; uint8_t serial_rx_buffer_head = 0; volatile uint8_t serial_rx_buffer_tail = 0; uint8_t serial_tx_buffer[RX_BUFFER_SIZE]; uint8_t serial_tx_buffer_head = 0; volatile uint8_t serial_tx_buffer_tail = 0; #ifdef ENABLE_XONXOFF volatile uint8_t flow_ctrl = XON_SENT; // Flow control state variable // Returns the number of bytes in the RX buffer. This replaces a typical byte counter to prevent // the interrupt and main programs from writing to the counter at the same time. static uint8_t get_serial_rx_buffer_count() { if (serial_rx_buffer_head == serial_rx_buffer_tail) { return(0); } if (serial_rx_buffer_head < serial_rx_buffer_tail) { return(serial_rx_buffer_tail-serial_rx_buffer_head); } return (RX_BUFFER_SIZE - (serial_rx_buffer_head-serial_rx_buffer_tail)); } #endif void USART_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; /********************以下為USART1配置**************************/ RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1 | RCC_APB2Periph_AFIO,ENABLE); /* * USART1_TX -> PA9 , USART1_RX -> PA10 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); USART_InitStructure.USART_BaudRate = 115200; USART_InitStructure.USART_WordLength = USART_WordLength_9b;//9位資料 USART_InitStructure.USART_StopBits = USART_StopBits_1;//1位停止位 USART_InitStructure.USART_Parity = USART_Parity_Even;//偶校驗 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //硬體流控制失能 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //傳送和接受使能 USART_Init(USART1, &USART_InitStructure); USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); // USART_ITConfig(USART1, USART_IT_TXE, ENABLE); /*********************************************************************************** void USART_Cmd(USART_TypeDef* USARTx, FunctionalState NewState) 使能或者失能USART外設 USARTx:x可以是1,2或者3,來選擇USART外設 NewState: 外設USARTx的新狀態 這個引數可以取:ENABLE或者DISABLE ***********************************************************************************/ USART_Cmd(USART1, ENABLE); USART_ClearITPendingBit(USART1, USART_IT_TC);//清除中斷TC位 MY_NVIC_Init(3,3,USART1_IRQChannel,2);//組2,最低優先順序 } /*********************************************************************** 函式名稱:void USART1_IRQHandler(void) 功 能:串列埠中斷服務函式 ***********************************************************************/ void USART1_IRQHandler(void) { if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收暫存器非空 { uint8_t data = USART1->DR; uint8_t next_head; // Pick off runtime command characters directly from the serial stream. These characters are // not passed into the buffer, but these set system state flag bits for runtime execution. switch (data) { case CMD_STATUS_REPORT: sys.execute |= EXEC_STATUS_REPORT; break; // Set as true case CMD_CYCLE_START: sys.execute |= EXEC_CYCLE_START; break; // Set as true case CMD_FEED_HOLD: sys.execute |= EXEC_FEED_HOLD; break; // Set as true case CMD_RESET: mc_reset(); break; // Call motion control reset routine. default: // Write character to buffer next_head = serial_rx_buffer_head + 1; if (next_head == RX_BUFFER_SIZE) { next_head = 0; } // Write data to buffer unless it is full. if (next_head != serial_rx_buffer_tail) { serial_rx_buffer[serial_rx_buffer_head] = data; serial_rx_buffer_head = next_head; } } // USART_ClearITPendingBit(USART1, USART_IT_RXNE); } if (USART_GetITStatus(USART1, USART_IT_TXE) != RESET) //寫資料暫存器空,可以寫資料 { // Temporary serial_tx_buffer_tail (to optimize for volatile) uint8_t tail = serial_tx_buffer_tail; // Send a byte from the buffer USART1->DR = serial_tx_buffer[tail]; // Update tail position tail++; if (tail == TX_BUFFER_SIZE) { tail = 0; } serial_tx_buffer_tail = tail; // Turn off Data Register Empty Interrupt to stop tx-streaming if this concludes the transfer //if (tail == serial_tx_buffer_head) { UCSR0B &= ~(1 << UDRIE0); } //USART_ClearITPendingBit(USART1, USART_IT_TXE); USART1->CR1&=~(1<<7); } } uint8_t serial_read() { uint8_t tail = serial_rx_buffer_tail; // Temporary serial_rx_buffer_tail (to optimize for volatile) if (serial_rx_buffer_head == tail) { return SERIAL_NO_DATA; } else { uint8_t data = serial_rx_buffer[tail]; tail++; if (tail == RX_BUFFER_SIZE) { tail = 0; } serial_rx_buffer_tail = tail; return data; } } void serial_write(uint8_t data) { // Calculate next head uint8_t next_head = serial_tx_buffer_head + 1; if (next_head == TX_BUFFER_SIZE) { next_head = 0; } // Wait until there is space in the buffer while (next_head == serial_tx_buffer_tail) { if (sys.execute & EXEC_RESET) { return; } // Only check for abort to avoid an endless loop. } // Store data and advance head serial_tx_buffer[serial_tx_buffer_head] = data; serial_tx_buffer_head = next_head; // Enable Data Register Empty Interrupt to make sure tx-streaming is running //UCSR0B |= (1 << UDRIE0); //傳送緩衝區空中斷使能,使其進入中斷 USART_ITConfig(USART1, USART_IT_TXE, ENABLE); } /*comment by zjk void serial_init() { // Set baud rate #if BAUD_RATE < 57600 uint16_t UBRR0_value = ((F_CPU / (8L * BAUD_RATE)) - 1)/2 ; UCSR0A &= ~(1 << U2X0); // baud doubler off - Only needed on Uno XXX #else uint16_t UBRR0_value = ((F_CPU / (4L * BAUD_RATE)) - 1)/2; UCSR0A |= (1 << U2X0); // baud doubler on for high baud rates, i.e. 115200 #endif UBRR0H = UBRR0_value >> 8; UBRR0L = UBRR0_value; // enable rx and tx UCSR0B |= 1<<RXEN0; UCSR0B |= 1<<TXEN0; // enable interrupt on complete reception of a byte UCSR0B |= 1<<RXCIE0; // defaults to 8-bit, no parity, 1 stop bit } void serial_write(uint8_t data) { // Calculate next head uint8_t next_head = serial_tx_buffer_head + 1; if (next_head == TX_BUFFER_SIZE) { next_head = 0; } // Wait until there is space in the buffer while (next_head == serial_tx_buffer_tail) { if (sys.execute & EXEC_RESET) { return; } // Only check for abort to avoid an endless loop. } // Store data and advance head serial_tx_buffer[serial_tx_buffer_head] = data; serial_tx_buffer_head = next_head; // Enable Data Register Empty Interrupt to make sure tx-streaming is running UCSR0B |= (1 << UDRIE0); } // Data Register Empty Interrupt handler ISR(SERIAL_UDRE) { // Temporary serial_tx_buffer_tail (to optimize for volatile) uint8_t tail = serial_tx_buffer_tail; #ifdef ENABLE_XONXOFF 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 { // Send a byte from the buffer UDR0 = serial_tx_buffer[tail]; // Update tail position tail++; if (tail == TX_BUFFER_SIZE) { tail = 0; } serial_tx_buffer_tail = tail; } // Turn off Data Register Empty Interrupt to stop tx-streaming if this concludes the transfer if (tail == serial_tx_buffer_head) { UCSR0B &= ~(1 << UDRIE0); } } uint8_t serial_read() { uint8_t tail = serial_rx_buffer_tail; // Temporary serial_rx_buffer_tail (to optimize for volatile) if (serial_rx_buffer_head == tail) { return SERIAL_NO_DATA; } else { uint8_t data = serial_rx_buffer[tail]; tail++; if (tail == RX_BUFFER_SIZE) { tail = 0; } serial_rx_buffer_tail = tail; #ifdef ENABLE_XONXOFF if ((get_serial_rx_buffer_count() < serial_rx_buffer_LOW) && flow_ctrl == XOFF_SENT) { flow_ctrl = SEND_XON; UCSR0B |= (1 << UDRIE0); // Force TX } #endif return data; } } ISR(SERIAL_RX) { uint8_t data = UDR0; uint8_t next_head; // Pick off runtime command characters directly from the serial stream. These characters are // not passed into the buffer, but these set system state flag bits for runtime execution. switch (data) { case CMD_STATUS_REPORT: sys.execute |= EXEC_STATUS_REPORT; break; // Set as true case CMD_CYCLE_START: sys.execute |= EXEC_CYCLE_START; break; // Set as true case CMD_FEED_HOLD: sys.execute |= EXEC_FEED_HOLD; break; // Set as true case CMD_RESET: mc_reset(); break; // Call motion control reset routine. default: // Write character to buffer next_head = serial_rx_buffer_head + 1; if (next_head == RX_BUFFER_SIZE) { next_head = 0; } // Write data to buffer unless it is full. if (next_head != serial_rx_buffer_tail) { serial_rx_buffer[serial_rx_buffer_head] = data; serial_rx_buffer_head = next_head; #ifdef ENABLE_XONXOFF if ((get_serial_rx_buffer_count() >= serial_rx_buffer_FULL) && flow_ctrl == XON_SENT) { flow_ctrl = SEND_XOFF; UCSR0B |= (1 << UDRIE0); // Force TX } #endif } } } */ void serial_reset_read_buffer() { serial_rx_buffer_tail = serial_rx_buffer_head; #ifdef ENABLE_XONXOFF flow_ctrl = XON_SENT; #endif }