887 lines
24 KiB
C
887 lines
24 KiB
C
|
|
// API portu szeregowego
|
|
/*
|
|
USART1 - RS485
|
|
USART2 - RS232 - porty nie tolerują 5V,
|
|
USART3 - RS485
|
|
|
|
|
|
*/
|
|
|
|
#include "serial.h"
|
|
#include "gpio.h"
|
|
#include "../error.h"
|
|
#include "stm32f10x.h"
|
|
#include <stdlib.h>
|
|
#include <stdint.h>
|
|
|
|
|
|
//bufory nadawcze/odbiorze portów szeregowych
|
|
USART_data_t USART1_data,USART2_data,USART3_data,UART4_data,UART5_data;
|
|
|
|
//USART5 - transmisja bez DMA, na przerwaniach
|
|
//licznik bajtów do wysłania
|
|
uint16_t UART5_size;
|
|
//wskazniki do aktualnie wysyłanych/odebranych danych (aktualizowane w przerwaniu)
|
|
uint8_t *UART5_rxptr,*UART5_txptr;
|
|
|
|
int8_t Serial_Initialize(USART_TypeDef * port, uint32_t mode, uint32_t baudrate, uint32_t timeguard)
|
|
{
|
|
USART_InitTypeDef USART_Conf;
|
|
GPIO_InitTypeDef GPIO_Conf;
|
|
DMA_InitTypeDef DMA_Conf;
|
|
NVIC_InitTypeDef NVIC_Conf;
|
|
|
|
//alokacja pamięci na bufory i konfiguracja wejśc/wyjść
|
|
switch((uint32_t)port)
|
|
{
|
|
case (uint32_t)USART1:
|
|
#ifdef USE_USART1
|
|
USART1_data.txbuf=(uint8_t*)malloc(USART_BSIZE);
|
|
USART1_data.rxbuf=(uint8_t*)malloc(USART_BSIZE);
|
|
USART1_data.dptr=USART1_data.rxbuf;
|
|
|
|
/* Zegar GPIOA,GPIOB,USART1,DMA1 */
|
|
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
|
|
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_USART1, ENABLE);
|
|
|
|
//TX1 - wyjście PERIPH
|
|
GPIO_Conf.GPIO_Pin=TX1;
|
|
GPIO_Conf.GPIO_Mode=GPIO_Mode_AF_PP;
|
|
GPIO_Conf.GPIO_Speed=GPIO_Speed_50MHz;
|
|
GPIO_Init(GPIOA,&GPIO_Conf);
|
|
//RX1 - wejście
|
|
GPIO_Conf.GPIO_Pin=RX1;
|
|
GPIO_Conf.GPIO_Mode=GPIO_Mode_IN_FLOATING;
|
|
GPIO_Init(GPIOA,&GPIO_Conf);
|
|
#else
|
|
return NO_PORT;
|
|
#endif
|
|
break;
|
|
|
|
case (uint32_t)USART2:
|
|
#ifdef USE_USART2
|
|
USART2_data.txbuf=(uint8_t*)malloc(USART_BSIZE);
|
|
USART2_data.rxbuf=(uint8_t*)malloc(USART_BSIZE);
|
|
USART2_data.dptr=USART2_data.rxbuf;
|
|
|
|
/* Zegar GPIOA,USART2 */
|
|
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
|
|
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
|
|
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
|
|
|
|
|
|
//TX1 - wyjście PERIPH
|
|
GPIO_Conf.GPIO_Pin=TX2;
|
|
GPIO_Conf.GPIO_Mode=GPIO_Mode_AF_PP;
|
|
GPIO_Conf.GPIO_Speed=GPIO_Speed_50MHz;
|
|
GPIO_Init(GPIOA,&GPIO_Conf);
|
|
//RX1 - wejście
|
|
GPIO_Conf.GPIO_Pin=RX2;
|
|
GPIO_Conf.GPIO_Mode=GPIO_Mode_IN_FLOATING;
|
|
GPIO_Init(GPIOA,&GPIO_Conf);
|
|
#else
|
|
return NO_PORT;
|
|
#endif
|
|
break;
|
|
|
|
case (uint32_t)USART3:
|
|
#ifdef USE_USART3
|
|
USART3_data.txbuf=(uint8_t*)malloc(USART_BSIZE);
|
|
USART3_data.rxbuf=(uint8_t*)malloc(USART_BSIZE);
|
|
USART3_data.dptr=USART3_data.rxbuf;
|
|
|
|
/* Zegar GPIOB,USART3,DMA1 */
|
|
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
|
|
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
|
|
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
|
|
|
|
//TX3 - wyjście PERIPH
|
|
GPIO_Conf.GPIO_Pin=TX3;
|
|
GPIO_Conf.GPIO_Mode=GPIO_Mode_AF_PP;
|
|
GPIO_Conf.GPIO_Speed=GPIO_Speed_50MHz;
|
|
GPIO_Init(GPIOB,&GPIO_Conf);
|
|
//RX3 - wejście
|
|
GPIO_Conf.GPIO_Pin=RX3;
|
|
GPIO_Conf.GPIO_Mode=GPIO_Mode_IN_FLOATING;
|
|
GPIO_Init(GPIOB,&GPIO_Conf);
|
|
#else
|
|
return NO_PORT;
|
|
#endif
|
|
|
|
break;
|
|
|
|
case (uint32_t)UART4:
|
|
#ifdef USE_UART4
|
|
UART4_data.txbuf=(uint8_t*)malloc(USART_BSIZE);
|
|
UART4_data.rxbuf=(uint8_t*)malloc(USART_BSIZE);
|
|
UART4_data.dptr=UART4_data.rxbuf;
|
|
|
|
/* Zegar GPIOB,GPIOC,UART4,DMA2 */
|
|
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2,ENABLE);
|
|
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC, ENABLE);
|
|
RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4, ENABLE);
|
|
|
|
//TX4 - wyjście PERIPH
|
|
GPIO_Conf.GPIO_Pin=TX4;
|
|
GPIO_Conf.GPIO_Mode=GPIO_Mode_AF_PP;
|
|
GPIO_Conf.GPIO_Speed=GPIO_Speed_50MHz;
|
|
GPIO_Init(GPIOC,&GPIO_Conf);
|
|
//RX4 - wejście
|
|
GPIO_Conf.GPIO_Pin=RX4;
|
|
GPIO_Conf.GPIO_Mode=GPIO_Mode_IN_FLOATING;
|
|
GPIO_Init(GPIOC,&GPIO_Conf);
|
|
//RW4 - wyjście GPIO
|
|
GPIO_Conf.GPIO_Pin=RW4;
|
|
GPIO_Conf.GPIO_Mode=GPIO_Mode_Out_PP;
|
|
GPIO_Init(GPIOB,&GPIO_Conf);
|
|
|
|
//RS-485 w tryb odbioru
|
|
PIO_Reset(GPIOB,RW4);
|
|
#else
|
|
return NO_PORT;
|
|
#endif
|
|
|
|
break;
|
|
|
|
case (uint32_t)UART5:
|
|
#ifdef USE_UART5
|
|
UART5_data.txbuf=(uint8_t*)malloc(USART_BSIZE);
|
|
UART5_data.rxbuf=(uint8_t*)malloc(USART_BSIZE);
|
|
UART5_data.dptr=UART5_data.rxbuf;
|
|
//dla portu UART5 ustaw dodatkowo wskaźnik UART5_rxptr i wyzeruj ilośc wysyłanych danych
|
|
UART5_rxptr=UART5_data.rxbuf;
|
|
UART5_size=0;
|
|
|
|
/* Zegar GPIOB,UART5 */
|
|
RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART5, ENABLE);
|
|
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD, ENABLE);
|
|
|
|
//TX5 - wyjście PERIPH
|
|
GPIO_Conf.GPIO_Pin=TX5;
|
|
GPIO_Conf.GPIO_Mode=GPIO_Mode_AF_PP;
|
|
GPIO_Conf.GPIO_Speed=GPIO_Speed_50MHz;
|
|
GPIO_Init(GPIOC,&GPIO_Conf);
|
|
//RX3 - wejście
|
|
GPIO_Conf.GPIO_Pin=RX5;
|
|
GPIO_Conf.GPIO_Mode=GPIO_Mode_IN_FLOATING;
|
|
GPIO_Init(GPIOD,&GPIO_Conf);
|
|
#else
|
|
return NO_PORT;
|
|
#endif
|
|
|
|
break;
|
|
|
|
default:
|
|
return NO_PORT;
|
|
}
|
|
//konfiguracja potru szeregowego
|
|
//baudrate
|
|
USART_Conf.USART_BaudRate=baudrate;
|
|
|
|
//mode - ignorowane, na razie tylko 8N1
|
|
USART_Conf.USART_WordLength=USART_WordLength_8b;
|
|
USART_Conf.USART_Parity=USART_Parity_No;
|
|
USART_Conf.USART_StopBits=USART_StopBits_1;
|
|
USART_Conf.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
|
|
|
|
// włącznadajnik i odbiornik
|
|
USART_Conf.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
|
|
|
|
USART_Init(port, &USART_Conf);
|
|
|
|
//włącz DMA (brak DMA dla UART5)
|
|
if(port!=UART5)
|
|
USART_DMACmd(port, USART_DMAReq_Rx|USART_DMAReq_Tx, ENABLE);
|
|
//port UART5 działa na przerwaniach, nie na DMA
|
|
else
|
|
{
|
|
#ifdef USE_UART5
|
|
NVIC_Conf.NVIC_IRQChannel=UART5_IRQn;
|
|
NVIC_Conf.NVIC_IRQChannelCmd=ENABLE;
|
|
NVIC_Conf.NVIC_IRQChannelPreemptionPriority=10;
|
|
NVIC_Conf.NVIC_IRQChannelSubPriority=0;
|
|
NVIC_Init(&NVIC_Conf);
|
|
|
|
|
|
//włącz przerwanie odbiorcze, wyłącz nadawcze
|
|
USART_ITConfig(port,USART_IT_RXNE,ENABLE);
|
|
USART_ITConfig(port,USART_IT_TXE,DISABLE);
|
|
#endif
|
|
}
|
|
|
|
|
|
//konfiguracja DMA
|
|
switch((uint32_t)port)
|
|
{
|
|
case (uint32_t)USART1:
|
|
#ifdef USE_USART1
|
|
//odbiór
|
|
DMA_Cmd(DMA1_Channel5, DISABLE);
|
|
DMA_DeInit(DMA1_Channel5);
|
|
DMA_Conf.DMA_BufferSize = USART_BSIZE;
|
|
DMA_Conf.DMA_DIR = DMA_DIR_PeripheralSRC;
|
|
DMA_Conf.DMA_M2M = DMA_M2M_Disable;
|
|
DMA_Conf.DMA_MemoryBaseAddr = (uint32_t)USART1_data.rxbuf;
|
|
DMA_Conf.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
|
|
DMA_Conf.DMA_MemoryInc = DMA_MemoryInc_Enable;
|
|
DMA_Conf.DMA_Mode=DMA_Mode_Circular;
|
|
DMA_Conf.DMA_PeripheralBaseAddr = (uint32_t)&(USART1->DR);
|
|
DMA_Conf.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
|
|
DMA_Conf.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
|
|
DMA_Conf.DMA_Priority = DMA_Priority_VeryHigh;
|
|
DMA_Init(DMA1_Channel5,&DMA_Conf);
|
|
DMA_Cmd(DMA1_Channel5, ENABLE);
|
|
|
|
//nadawanie
|
|
DMA_Cmd(DMA1_Channel4, DISABLE);
|
|
DMA_DeInit(DMA1_Channel4);
|
|
DMA_Conf.DMA_DIR = DMA_DIR_PeripheralDST;
|
|
DMA_Conf.DMA_MemoryBaseAddr = (uint32_t)USART1_data.txbuf;
|
|
DMA_Conf.DMA_Mode=DMA_Mode_Normal;
|
|
DMA_Init(DMA1_Channel4,&DMA_Conf);
|
|
//przerwanie DMA CH4
|
|
NVIC_Conf.NVIC_IRQChannel=DMA1_Channel4_IRQn;
|
|
NVIC_Conf.NVIC_IRQChannelCmd=ENABLE;
|
|
NVIC_Conf.NVIC_IRQChannelPreemptionPriority=10;
|
|
NVIC_Conf.NVIC_IRQChannelSubPriority=0;
|
|
NVIC_Init(&NVIC_Conf);
|
|
#endif
|
|
break;
|
|
|
|
case (uint32_t)USART2:
|
|
#ifdef USE_USART2
|
|
//odbiór
|
|
DMA_Cmd(DMA1_Channel6, DISABLE);
|
|
DMA_DeInit(DMA1_Channel6);
|
|
DMA_Conf.DMA_BufferSize = USART_BSIZE;
|
|
DMA_Conf.DMA_DIR = DMA_DIR_PeripheralSRC;
|
|
DMA_Conf.DMA_M2M = DMA_M2M_Disable;
|
|
DMA_Conf.DMA_MemoryBaseAddr = (uint32_t)USART2_data.rxbuf;
|
|
DMA_Conf.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
|
|
DMA_Conf.DMA_MemoryInc = DMA_MemoryInc_Enable;
|
|
DMA_Conf.DMA_Mode=DMA_Mode_Circular;
|
|
DMA_Conf.DMA_PeripheralBaseAddr = (uint32_t)&(USART2->DR);
|
|
DMA_Conf.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
|
|
DMA_Conf.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
|
|
DMA_Conf.DMA_Priority = DMA_Priority_VeryHigh;
|
|
DMA_Init(DMA1_Channel6,&DMA_Conf);
|
|
DMA_Cmd(DMA1_Channel6, ENABLE);
|
|
|
|
//nadawanie
|
|
DMA_Cmd(DMA1_Channel7, DISABLE);
|
|
DMA_DeInit(DMA1_Channel7);
|
|
DMA_Conf.DMA_DIR = DMA_DIR_PeripheralDST;
|
|
DMA_Conf.DMA_MemoryBaseAddr = (uint32_t)USART2_data.txbuf;
|
|
DMA_Conf.DMA_Mode=DMA_Mode_Normal;
|
|
DMA_Init(DMA1_Channel7,&DMA_Conf);
|
|
//przerwanie DMA CH7
|
|
NVIC_Conf.NVIC_IRQChannel=DMA1_Channel7_IRQn;
|
|
NVIC_Conf.NVIC_IRQChannelCmd=ENABLE;
|
|
NVIC_Conf.NVIC_IRQChannelPreemptionPriority=10;
|
|
NVIC_Conf.NVIC_IRQChannelSubPriority=0;
|
|
NVIC_Init(&NVIC_Conf);
|
|
#endif
|
|
break;
|
|
|
|
case (uint32_t)USART3:
|
|
#ifdef USE_USART3
|
|
//odbiór
|
|
DMA_Cmd(DMA1_Channel3, DISABLE);
|
|
DMA_DeInit(DMA1_Channel3);
|
|
DMA_Conf.DMA_BufferSize = USART_BSIZE;
|
|
DMA_Conf.DMA_DIR = DMA_DIR_PeripheralSRC;
|
|
DMA_Conf.DMA_M2M = DMA_M2M_Disable;
|
|
DMA_Conf.DMA_MemoryBaseAddr = (uint32_t)USART3_data.rxbuf;
|
|
DMA_Conf.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
|
|
DMA_Conf.DMA_MemoryInc = DMA_MemoryInc_Enable;
|
|
DMA_Conf.DMA_Mode=DMA_Mode_Circular;
|
|
DMA_Conf.DMA_PeripheralBaseAddr = (uint32_t)&(USART3->DR);
|
|
DMA_Conf.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
|
|
DMA_Conf.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
|
|
DMA_Conf.DMA_Priority = DMA_Priority_VeryHigh;
|
|
DMA_Init(DMA1_Channel3,&DMA_Conf);
|
|
DMA_Cmd(DMA1_Channel3, ENABLE);
|
|
|
|
//nadawanie
|
|
DMA_Cmd(DMA1_Channel2, DISABLE);
|
|
DMA_DeInit(DMA1_Channel2);
|
|
DMA_Conf.DMA_DIR = DMA_DIR_PeripheralDST;
|
|
DMA_Conf.DMA_MemoryBaseAddr = (uint32_t)USART3_data.txbuf;
|
|
DMA_Conf.DMA_Mode=DMA_Mode_Normal;
|
|
DMA_Init(DMA1_Channel2,&DMA_Conf);
|
|
//przerwanie DMA CH2
|
|
NVIC_Conf.NVIC_IRQChannel=DMA1_Channel2_IRQn;
|
|
NVIC_Conf.NVIC_IRQChannelCmd=ENABLE;
|
|
NVIC_Conf.NVIC_IRQChannelPreemptionPriority=10;
|
|
NVIC_Conf.NVIC_IRQChannelSubPriority=0;
|
|
NVIC_Init(&NVIC_Conf);
|
|
#endif
|
|
break;
|
|
|
|
case (uint32_t)UART4:
|
|
#ifdef USE_UART3
|
|
//odbiór
|
|
DMA_Cmd(DMA2_Channel3, DISABLE);
|
|
DMA_DeInit(DMA2_Channel3);
|
|
DMA_Conf.DMA_BufferSize = USART_BSIZE;
|
|
DMA_Conf.DMA_DIR = DMA_DIR_PeripheralSRC;
|
|
DMA_Conf.DMA_M2M = DMA_M2M_Disable;
|
|
DMA_Conf.DMA_MemoryBaseAddr = (uint32_t)UART4_data.rxbuf;
|
|
DMA_Conf.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
|
|
DMA_Conf.DMA_MemoryInc = DMA_MemoryInc_Enable;
|
|
DMA_Conf.DMA_Mode=DMA_Mode_Circular;
|
|
DMA_Conf.DMA_PeripheralBaseAddr = (uint32_t)&(UART4->DR);
|
|
DMA_Conf.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
|
|
DMA_Conf.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
|
|
DMA_Conf.DMA_Priority = DMA_Priority_VeryHigh;
|
|
DMA_Init(DMA2_Channel3,&DMA_Conf);
|
|
DMA_Cmd(DMA2_Channel3, ENABLE);
|
|
|
|
//nadawanie
|
|
DMA_Cmd(DMA2_Channel5, DISABLE);
|
|
DMA_DeInit(DMA2_Channel5);
|
|
DMA_Conf.DMA_DIR = DMA_DIR_PeripheralDST;
|
|
DMA_Conf.DMA_MemoryBaseAddr = (uint32_t)UART4_data.txbuf;
|
|
DMA_Conf.DMA_Mode=DMA_Mode_Normal;
|
|
DMA_Init(DMA2_Channel5,&DMA_Conf);
|
|
//przerwanie DMA2 CH45
|
|
NVIC_Conf.NVIC_IRQChannel=DMA2_Channel4_5_IRQn;
|
|
NVIC_Conf.NVIC_IRQChannelCmd=ENABLE;
|
|
NVIC_Conf.NVIC_IRQChannelPreemptionPriority=10;
|
|
NVIC_Conf.NVIC_IRQChannelSubPriority=0;
|
|
NVIC_Init(&NVIC_Conf);
|
|
#endif
|
|
break;
|
|
}
|
|
|
|
//włącz port
|
|
USART_Cmd(port, ENABLE);
|
|
|
|
}
|
|
|
|
int8_t Serial_Ready(USART_TypeDef * port)
|
|
{
|
|
switch((uint32_t)port)
|
|
{
|
|
case (uint32_t)USART1:
|
|
if( !((DMA1_Channel4->CCR)& DMA_CCR4_TCIE) )
|
|
return 1;
|
|
else
|
|
return 0;
|
|
|
|
case (uint32_t)USART2:
|
|
if( !((DMA1_Channel7->CCR)& DMA_CCR7_TCIE) )
|
|
return 1;
|
|
else
|
|
return 0;
|
|
|
|
case (uint32_t)USART3:
|
|
if( !((DMA1_Channel2->CCR)& DMA_CCR2_TCIE) )
|
|
return 1;
|
|
else
|
|
return 0;
|
|
|
|
case (uint32_t)UART4:
|
|
if( !((DMA2_Channel5->CCR)& DMA_CCR5_TCIE) )
|
|
return 1;
|
|
else
|
|
return 0;
|
|
|
|
case (uint32_t)UART5:
|
|
if( !UART5_size ) // Sprzawdzam czy zostały wysłane wszytskie dane.
|
|
return 1;
|
|
else
|
|
return 0;
|
|
|
|
default:
|
|
return NO_PORT;
|
|
|
|
}
|
|
}
|
|
|
|
//Nadawanie
|
|
|
|
int __putchar(int c)
|
|
{
|
|
while( !(USART2->SR&USART_SR_TXE) );
|
|
USART2->DR = c;
|
|
}
|
|
|
|
//Nadawanie
|
|
int32_t Serial_Send(USART_TypeDef * port, uint8_t *data, uint16_t len)
|
|
{
|
|
|
|
uint8_t *src,*dst;
|
|
uint16_t i;
|
|
//Sprawdź który port
|
|
switch((uint32_t)port)
|
|
{
|
|
case (uint32_t)USART1:
|
|
#ifdef USE_USART1
|
|
//sprawdź stan portu - jeżeli przerwanie TC jest włączone to transmisja trwa
|
|
if( (DMA1_Channel4->CCR)& DMA_CCR4_TCIE )
|
|
return USART_BUSY;
|
|
|
|
//skopiuj dane
|
|
dst=USART1_data.txbuf;
|
|
src=data;
|
|
for(i=0;i<len;i++)
|
|
*dst++=*src++;
|
|
|
|
|
|
//transmisja przez DMA
|
|
DMA_Cmd(DMA1_Channel4, DISABLE);
|
|
DMA1_Channel4->CNDTR = len;
|
|
DMA_Cmd(DMA1_Channel4, ENABLE);
|
|
|
|
//włącz przerwanie po zakończeniu transmisji
|
|
DMA_ITConfig(DMA1_Channel4,DMA_IT_TC|DMA_IT_TE,ENABLE);
|
|
|
|
//zwróć ilość wysłanych bajtów
|
|
return len;
|
|
#else
|
|
return NO_PORT;
|
|
#endif
|
|
|
|
case (uint32_t)USART2:
|
|
#ifdef USE_USART2
|
|
//sprawdź stan portu - jeżeli przerwanie TC jest włączone to transmisja trwa
|
|
if( (DMA1_Channel7->CCR)& DMA_CCR7_TCIE)
|
|
return USART_BUSY;
|
|
|
|
//skopiuj dane
|
|
dst=USART2_data.txbuf;
|
|
src=data;
|
|
for(i=0;i<len;i++)
|
|
*dst++=*src++;
|
|
|
|
//transmisja przez DMA
|
|
DMA_Cmd(DMA1_Channel7, DISABLE);
|
|
DMA1_Channel7->CNDTR = len;
|
|
DMA_Cmd(DMA1_Channel7, ENABLE);
|
|
|
|
//włącz przerwanie po zakończeniu transmisji
|
|
DMA_ITConfig(DMA1_Channel7,DMA_IT_TC|DMA_IT_TE,ENABLE);
|
|
|
|
//zwróć ilość wysłanych bajtów
|
|
return len;
|
|
#else
|
|
return NO_PORT;
|
|
#endif
|
|
|
|
case (uint32_t)USART3:
|
|
#ifdef USE_USART3
|
|
//sprawdź stan portu - jeżeli przerwanie TC jest włączone to transmisja trwa
|
|
if( (DMA1_Channel2->CCR)& DMA_CCR2_TCIE)
|
|
return USART_BUSY;
|
|
|
|
//skopiuj dane
|
|
dst=USART3_data.txbuf;
|
|
src=data;
|
|
for(i=0;i<len;i++)
|
|
*dst++=*src++;
|
|
|
|
//transmisja przez DMA
|
|
DMA_Cmd(DMA1_Channel2, DISABLE);
|
|
DMA1_Channel2->CNDTR = len;
|
|
DMA_Cmd(DMA1_Channel2, ENABLE);
|
|
|
|
//włącz przerwanie po zakończeniu transmisji
|
|
DMA_ITConfig(DMA1_Channel2,DMA_IT_TC|DMA_IT_TE,ENABLE);
|
|
|
|
//zwróć ilość wysłanych bajtów
|
|
return len;
|
|
#else
|
|
return NO_PORT;
|
|
#endif
|
|
|
|
case (uint32_t)UART4:
|
|
#ifdef USE_UART4
|
|
//sprawdź stan portu - jeżeli przerwanie TC jest włączone to transmisja trwa
|
|
if( (DMA2_Channel5->CCR)& DMA_CCR5_TCIE )
|
|
return USART_BUSY;
|
|
|
|
//skopiuj dane
|
|
dst=UART4_data.txbuf;
|
|
src=data;
|
|
for(i=0;i<len;i++)
|
|
*dst++=*src++;
|
|
|
|
//RS-485 w tryb nadawania
|
|
PIO_Set(GPIOB,RW4);
|
|
|
|
//transmisja przez DMA
|
|
DMA_Cmd(DMA2_Channel5, DISABLE);
|
|
DMA2_Channel5->CNDTR = len;
|
|
DMA_Cmd(DMA2_Channel5, ENABLE);
|
|
|
|
//włącz przerwanie po zakończeniu transmisji
|
|
DMA_ITConfig(DMA2_Channel5,DMA_IT_TC|DMA_IT_TE,ENABLE);
|
|
|
|
//zwróć ilość wysłanych bajtów
|
|
return len;
|
|
#else
|
|
return NO_PORT;
|
|
#endif
|
|
|
|
case (uint32_t)UART5:
|
|
#ifdef USE_UART5
|
|
//sprawdź stan portu - jezeli rozmiar danych jest różny od zera to transmisja trwa
|
|
if( UART5_size )
|
|
return USART_BUSY;
|
|
|
|
//skopiuj dane
|
|
dst=UART5_data.txbuf;
|
|
src=data;
|
|
for(i=0;i<len;i++)
|
|
*dst++=*src++;
|
|
|
|
//zapisz ilość bajtów do wysłania
|
|
UART5_size=len;
|
|
|
|
//ustaw wskaźnik na początek bufora
|
|
UART5_txptr=UART5_data.txbuf;
|
|
|
|
//włącz przerwanie nadawcze
|
|
USART_ITConfig(port,USART_IT_TXE,ENABLE);
|
|
|
|
//zwróć ilość wysłanych bajtów
|
|
return len;
|
|
#else
|
|
return NO_PORT;
|
|
#endif
|
|
|
|
default:
|
|
return NO_PORT;
|
|
}
|
|
}
|
|
|
|
//Odbiór
|
|
|
|
int32_t Serial_Receive(USART_TypeDef *port, uint8_t *user_buffer, uint16_t len)
|
|
{
|
|
uint16_t i,start,end,remaining,count;
|
|
|
|
switch((uint32_t)port)
|
|
{
|
|
case (uint32_t)USART1:
|
|
//oblicz ile jest danych w buforze
|
|
start = USART1_data.dptr-USART1_data.rxbuf;
|
|
end = USART_BSIZE - (DMA1_Channel5->CNDTR);
|
|
if(end>=start)
|
|
remaining=end-start;
|
|
else
|
|
remaining=(USART_BSIZE-(start-end));
|
|
|
|
//ile danych wyslac uzytkownikowi
|
|
if(len>=remaining)
|
|
count=remaining;
|
|
else
|
|
count=len;
|
|
|
|
//kopiuje dane do bufora użytkownika
|
|
for(i=0;i<count;i++)
|
|
{
|
|
*user_buffer++=*(USART1_data.dptr)++;
|
|
|
|
//kraniec wewnętrznego bufora. Przestaw wskaźnik na początek.
|
|
if(USART1_data.dptr==USART1_data.rxbuf+USART_BSIZE)
|
|
USART1_data.dptr=USART1_data.rxbuf;
|
|
|
|
}
|
|
return count;
|
|
|
|
case (uint32_t)USART2:
|
|
//oblicz ile jest danych w buforze
|
|
start = USART2_data.dptr-USART2_data.rxbuf;
|
|
end = USART_BSIZE - (DMA1_Channel6->CNDTR);
|
|
if(end>=start)
|
|
remaining=end-start;
|
|
else
|
|
remaining=(USART_BSIZE-(start-end));
|
|
|
|
//ile danych wyslac uzytkownikowi
|
|
if(len>=remaining)
|
|
count=remaining;
|
|
else
|
|
count=len;
|
|
|
|
//kopiuje dane do bufora użytkownika
|
|
for(i=0;i<count;i++)
|
|
{
|
|
*user_buffer++=*(USART2_data.dptr)++;
|
|
|
|
//kraniec wewnętrznego bufora. Przestaw wskaźnik na początek.
|
|
if(USART2_data.dptr==USART2_data.rxbuf+USART_BSIZE)
|
|
USART2_data.dptr=USART2_data.rxbuf;
|
|
|
|
}
|
|
return count;
|
|
|
|
case (uint32_t)USART3:
|
|
//oblicz ile jest danych w buforze
|
|
start = USART3_data.dptr-USART3_data.rxbuf;
|
|
end = USART_BSIZE - (DMA1_Channel3->CNDTR);
|
|
if(end>=start)
|
|
remaining=end-start;
|
|
else
|
|
remaining=(USART_BSIZE-(start-end));
|
|
|
|
//ile danych wyslac uzytkownikowi
|
|
if(len>=remaining)
|
|
count=remaining;
|
|
else
|
|
count=len;
|
|
|
|
//kopiuje dane do bufora użytkownika
|
|
for(i=0;i<count;i++)
|
|
{
|
|
*user_buffer++=*(USART3_data.dptr)++;
|
|
|
|
//kraniec wewnętrznego bufora. Przestaw wskaźnik na początek.
|
|
if(USART3_data.dptr==USART3_data.rxbuf+USART_BSIZE)
|
|
USART3_data.dptr=USART3_data.rxbuf;
|
|
|
|
}
|
|
return count;
|
|
|
|
case (uint32_t)UART4:
|
|
//oblicz ile jest danych w buforze
|
|
start = UART4_data.dptr-UART4_data.rxbuf;
|
|
end = USART_BSIZE - (DMA2_Channel3->CNDTR);
|
|
if(end>=start)
|
|
remaining=end-start;
|
|
else
|
|
remaining=(USART_BSIZE-(start-end));
|
|
|
|
//ile danych wyslac uzytkownikowi
|
|
if(len>=remaining)
|
|
count=remaining;
|
|
else
|
|
count=len;
|
|
|
|
//kopiuje dane do bufora użytkownika
|
|
for(i=0;i<count;i++)
|
|
{
|
|
*user_buffer++=*(UART4_data.dptr)++;
|
|
|
|
//kraniec wewnętrznego bufora. Przestaw wskaźnik na początek.
|
|
if(UART4_data.dptr==UART4_data.rxbuf+USART_BSIZE)
|
|
UART4_data.dptr=UART4_data.rxbuf;
|
|
|
|
}
|
|
return count;
|
|
|
|
case (uint32_t)UART5:
|
|
//oblicz ile jest danych w buforze
|
|
start = UART5_data.dptr-UART5_data.rxbuf;
|
|
end = UART5_rxptr-UART5_data.rxbuf;
|
|
if(end>=start)
|
|
remaining=end-start;
|
|
else
|
|
remaining=(USART_BSIZE-(start-end));
|
|
|
|
//ile danych wyslac uzytkownikowi
|
|
if(len>=remaining)
|
|
count=remaining;
|
|
else
|
|
count=len;
|
|
|
|
//kopiuje dane do bufora użytkownika
|
|
for(i=0;i<count;i++)
|
|
{
|
|
*user_buffer++=*(UART5_data.dptr)++;
|
|
|
|
//kraniec wewnętrznego bufora. Przestaw wskaźnik na początek.
|
|
if(UART5_data.dptr==UART5_data.rxbuf+USART_BSIZE)
|
|
UART5_data.dptr=UART5_data.rxbuf;
|
|
|
|
}
|
|
return count;
|
|
default:
|
|
return NO_PORT;
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
//obsługa przerwań
|
|
|
|
void DMA1_Channel2_IRQHandler(void)
|
|
{
|
|
#ifdef USE_USART3
|
|
//koniec transferu
|
|
if((DMA1->ISR)&DMA1_FLAG_TC2)
|
|
{
|
|
//wyczyść flagę przerwania
|
|
DMA1->IFCR = DMA1_FLAG_GL2;
|
|
|
|
//wyłącz przerwanie
|
|
(DMA1_Channel2->CCR) &= ~DMA_IT_TC;
|
|
}
|
|
//błąd transmisji
|
|
else if((DMA1->ISR)&DMA1_FLAG_TE2)
|
|
{
|
|
//wyczyść flagę przerwania
|
|
DMA1->IFCR = DMA1_FLAG_GL2;
|
|
|
|
//wyłącz przerwanie
|
|
(DMA1_Channel2->CCR) &= ~DMA_IT_TE;
|
|
|
|
//zatrzymaj pracę
|
|
while(1);
|
|
}
|
|
else
|
|
{
|
|
//zatrzymaj pracę
|
|
while(1);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void DMA1_Channel4_IRQHandler(void)
|
|
{
|
|
#ifdef USE_USART1
|
|
//koniec transferu
|
|
if((DMA1->ISR)&DMA1_FLAG_TC4)
|
|
{
|
|
//wyczyść flagę przerwania
|
|
DMA1->IFCR = DMA1_FLAG_GL4;
|
|
|
|
//czekaj aż port szeregowy nada ostatni znak
|
|
while(!((USART1->SR)&USART_SR_TC));
|
|
|
|
//wyłącz przerwanie
|
|
(DMA1_Channel4->CCR) &= ~DMA_IT_TC;
|
|
}
|
|
//błąd transmisji
|
|
else if((DMA1->ISR)&DMA1_FLAG_TE4)
|
|
{
|
|
//wyczyść flagę przerwania
|
|
DMA1->IFCR = DMA1_FLAG_GL4;
|
|
|
|
//wyłącz przerwanie
|
|
(DMA1_Channel4->CCR) &= ~DMA_IT_TE;
|
|
|
|
//zatrzymaj pracę
|
|
while(1);
|
|
}
|
|
else
|
|
{
|
|
//zatrzymaj pracę
|
|
while(1);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void DMA1_Channel7_IRQHandler(void)
|
|
{
|
|
#ifdef USE_USART2
|
|
//koniec transferu
|
|
if((DMA1->ISR)&DMA1_FLAG_TC7)
|
|
{
|
|
//wyczyść flagę przerwania
|
|
DMA1->IFCR = DMA1_FLAG_GL7;
|
|
|
|
//wyłącz przerwanie
|
|
(DMA1_Channel7->CCR) &= ~DMA_IT_TC;
|
|
}
|
|
//błąd transmisji
|
|
else if((DMA1->ISR)&DMA1_FLAG_TE7)
|
|
{
|
|
//wyczyść flagę przerwania
|
|
DMA1->IFCR = DMA1_FLAG_GL7;
|
|
|
|
//wyłącz przerwanie
|
|
(DMA1_Channel7->CCR) &= ~DMA_IT_TE;
|
|
|
|
//zatrzymaj pracę
|
|
while(1);
|
|
}
|
|
else
|
|
{
|
|
//zatrzymaj pracę
|
|
while(1);
|
|
}
|
|
#endif
|
|
}
|
|
void DMA2_Channel4_5_IRQHandler(void)
|
|
{
|
|
#ifdef USE_UART4
|
|
//koniec transferu
|
|
if((DMA2->ISR)&DMA2_FLAG_TC5)
|
|
{
|
|
//wyczyść flagę przerwania
|
|
DMA2->IFCR = DMA2_FLAG_GL2;
|
|
|
|
//czekaj aż port szeregowy nada ostatni znak
|
|
while(!(UART4->SR)&USART_SR_TC);
|
|
|
|
//RS-485 w tryb odbioru
|
|
PIO_Reset(GPIOB,RW4);
|
|
|
|
//wyłącz przerwanie
|
|
(DMA2_Channel5->CCR) &= ~DMA_IT_TC;
|
|
}
|
|
//błąd transmisji
|
|
else if((DMA2->ISR)&DMA2_FLAG_TE5)
|
|
{
|
|
//wyczyść flagę przerwania
|
|
DMA2->IFCR = DMA2_FLAG_GL5;
|
|
|
|
//RS-485 w tryb odbioru
|
|
PIO_Reset(GPIOB,RW4);
|
|
|
|
//wyłącz przerwanie
|
|
(DMA2_Channel5->CCR) &= ~DMA_IT_TE;
|
|
|
|
//zatrzymaj pracę
|
|
while(1);
|
|
}
|
|
else
|
|
{
|
|
//zatrzymaj pracę
|
|
while(1);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void UART5_IRQHandler(void)
|
|
{
|
|
#ifdef USE_UART5
|
|
//odebrano znak
|
|
if((UART5->SR)&USART_SR_RXNE)
|
|
{
|
|
//odczyt znaku
|
|
*UART5_rxptr++ = UART5->DR;
|
|
|
|
//koniec bufora odbiorczego. Przewiń wskaźnik na początek.
|
|
if(UART5_rxptr == (UART5_data.rxbuf+USART_BSIZE) )
|
|
UART5_rxptr=UART5_data.rxbuf;
|
|
}
|
|
|
|
//bufor nadawczy się opróżnił
|
|
else if((UART5->SR)&USART_SR_TXE)
|
|
{
|
|
|
|
//nadaj kolejny znak
|
|
UART5->DR = *UART5_txptr++;
|
|
|
|
//koniec transmisji
|
|
if(UART5_txptr == (UART5_data.txbuf+UART5_size) )
|
|
{
|
|
//
|
|
UART5_size=0;
|
|
USART_ITConfig(UART5,USART_IT_TXE,DISABLE);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
//zatrzymaj pracę
|
|
while(1);
|
|
}
|
|
#endif
|
|
} |