stm32_freertos_template/hw/serial.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
}