uart.c
430 lines
| 11.7 KiB
| text/x-c
|
CLexer
|
r14 | /*------------------------------------------------------------------------------ | ||
-- This file is a part of the libuc, microcontroler library | ||||
-- Copyright (C) 2011, Alexis Jeandet | ||||
-- | ||||
-- This program is free software; you can redistribute it and/or modify | ||||
-- it under the terms of the GNU General Public License as published by | ||||
-- the Free Software Foundation; either version 3 of the License, or | ||||
-- (at your option) any later version. | ||||
-- | ||||
-- This program is distributed in the hope that it will be useful, | ||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
-- GNU General Public License for more details. | ||||
-- | ||||
-- You should have received a copy of the GNU General Public License | ||||
-- along with this program; if not, write to the Free Software | ||||
|
r18 | -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
|
r14 | ------------------------------------------------------------------------------- | ||
-- Author : Alexis Jeandet | ||||
-- Mail : alexis.jeandet@gmail.com | ||||
-------------------------------------------------------------------------------*/ | ||||
|
r16 | #include <uart.h> | ||
#include <stm32f4xx_usart.h> | ||||
#include <stm32f4xx_rcc.h> | ||||
|
r18 | #include <stm32f4xx_gpio.h> | ||
#include <gpio.h> | ||||
#define GPIOGETPORT(gpio) ((GPIO_TypeDef*)(((((uint32_t)gpio) & (uint32_t)0x0000FF00)*(uint32_t)4) + (uint32_t)GPIOA)) | ||||
#define GPIOPORTNUM(gpio) (((uint32_t)(gpio) & (uint32_t)0x0000FF00)>>(uint32_t)8) | ||||
|
r14 | |||
|
r16 | int uartopen(int count ,uart_t* uart) | ||
{ | ||||
|
r18 | |||
switch(count) | ||||
{ | ||||
case 0: | ||||
uart->_dev = (void*)USART1; | ||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); | ||||
RCC_APB2PeriphResetCmd(RCC_APB2Periph_USART1, ENABLE); | ||||
RCC_APB2PeriphResetCmd(RCC_APB2Periph_USART1, DISABLE); | ||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); | ||||
((USART_TypeDef *)(uart->_dev))->CR3 &= ~((1<<8) + (1<<9)); | ||||
//uartenable(uart); | ||||
break; | ||||
case 1: | ||||
uart->_dev = (void*)USART2; | ||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); | ||||
RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART2, ENABLE); | ||||
RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART2, DISABLE); | ||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); | ||||
((USART_TypeDef *)(uart->_dev))->CR3 &= ~((1<<8) + (1<<9)); | ||||
//uartenable(uart); | ||||
break; | ||||
case 2: | ||||
uart->_dev = (void*)USART3; | ||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); | ||||
RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART3, ENABLE); | ||||
RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART3, DISABLE); | ||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); | ||||
((USART_TypeDef *)(uart->_dev))->CR3 &= ~((1<<8) + (1<<9)); | ||||
//uartenable(uart); | ||||
break; | ||||
case 3: | ||||
uart->_dev = (void*)UART4; | ||||
RCC_APB1PeriphResetCmd(RCC_APB1Periph_UART4, ENABLE); | ||||
RCC_APB1PeriphResetCmd(RCC_APB1Periph_UART4, DISABLE); | ||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4, ENABLE); | ||||
((USART_TypeDef *)(uart->_dev))->CR3 &= ~((1<<8) + (1<<9)); | ||||
//uartenable(uart); | ||||
break; | ||||
case 4: | ||||
uart->_dev = (void*)UART5; | ||||
RCC_APB1PeriphResetCmd(RCC_APB1Periph_UART5, ENABLE); | ||||
RCC_APB1PeriphResetCmd(RCC_APB1Periph_UART5, DISABLE); | ||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART5, ENABLE); | ||||
break; | ||||
case 5: | ||||
uart->_dev = (void*)USART6; | ||||
RCC_APB2PeriphResetCmd(RCC_APB2Periph_USART6, ENABLE); | ||||
RCC_APB2PeriphResetCmd(RCC_APB2Periph_USART6, DISABLE); | ||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART6, ENABLE); | ||||
break; | ||||
default: | ||||
break; | ||||
} | ||||
return 1; | ||||
|
r14 | } | ||
|
r18 | int uartopenandconfig(int count ,uart_t* uart,uint32_t cfg,uint32_t speed,uint32_t TXpin,uint32_t RXpin,uint32_t RTSpin,uint32_t CTSpin) | ||
{ | ||||
uartopen(count ,uart); | ||||
uart->cfg = cfg; | ||||
uart->speed = speed; | ||||
uartsetconfig(uart); | ||||
uartsetpins(uart,TXpin,RXpin,RTSpin,CTSpin); | ||||
return 1; | ||||
} | ||||
|
r16 | int uartclose(uart_t* uart) | ||
|
r14 | { | ||
|
r18 | switch((int)uart->_dev) | ||
{ | ||||
case (int)(void*)USART1: | ||||
uart->_dev = (void*)USART1; | ||||
RCC_APB2PeriphResetCmd(RCC_APB2Periph_USART1, ENABLE); | ||||
break; | ||||
case (int)(void*)USART2: | ||||
uart->_dev = (void*)USART2; | ||||
RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART2, ENABLE); | ||||
break; | ||||
case (int)(void*)USART3: | ||||
uart->_dev = (void*)USART3; | ||||
RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART3, ENABLE); | ||||
break; | ||||
case (int)(void*)UART4: | ||||
uart->_dev = (void*)UART4; | ||||
RCC_APB1PeriphResetCmd(RCC_APB1Periph_UART4, ENABLE); | ||||
break; | ||||
case (int)(void*)UART5: | ||||
uart->_dev = (void*)UART5; | ||||
RCC_APB1PeriphResetCmd(RCC_APB1Periph_UART5, ENABLE); | ||||
break; | ||||
case (int)(void*)USART6: | ||||
uart->_dev = (void*)USART6; | ||||
RCC_APB2PeriphResetCmd(RCC_APB2Periph_USART6, ENABLE); | ||||
break; | ||||
default: | ||||
break; | ||||
} | ||||
return 1; | ||||
} | ||||
int uartsetpins(uart_t* uart,uint32_t TXpin,uint32_t RXpin,uint32_t RTSpin,uint32_t CTSpin) | ||||
{ | ||||
gpio_t TX,RX,CTS,RTS; | ||||
TX = gpioopen(TXpin); | ||||
RX = gpioopen(RXpin); | ||||
TX |= gpiolowspeed | gpioaf | gpiopushpulltype | gpionopulltype; | ||||
RX |= gpiolowspeed | gpioaf | gpiopushpulltype | gpionopulltype; | ||||
gpiosetconfig(&TX); | ||||
gpiosetconfig(&RX); | ||||
uint8_t gpioAFuartx = GPIO_AF_USART1; | ||||
switch((int)uart->_dev) | ||||
{ | ||||
case (int)(void*)USART1: | ||||
gpioAFuartx = GPIO_AF_USART1; | ||||
break; | ||||
case (int)(void*)USART2: | ||||
gpioAFuartx = GPIO_AF_USART2; | ||||
break; | ||||
case (int)(void*)USART3: | ||||
gpioAFuartx = GPIO_AF_USART3; | ||||
break; | ||||
case (int)(void*)UART4: | ||||
gpioAFuartx = GPIO_AF_UART4; | ||||
break; | ||||
case (int)(void*)UART5: | ||||
gpioAFuartx = GPIO_AF_UART5; | ||||
break; | ||||
case (int)(void*)USART6: | ||||
gpioAFuartx = GPIO_AF_USART6; | ||||
break; | ||||
default: | ||||
break; | ||||
} | ||||
GPIO_PinAFConfig(GPIOGETPORT(TX), (uint8_t)(TX & 0xF), gpioAFuartx); | ||||
GPIO_PinAFConfig(GPIOGETPORT(TX), (uint8_t)(RX & 0xF), gpioAFuartx); | ||||
if((gpioAFuartx!=GPIO_AF_UART5) && (gpioAFuartx!=GPIO_AF_UART4)) | ||||
{ | ||||
if(CTSpin!=-1) | ||||
{ | ||||
CTS = gpioopen(CTSpin); | ||||
CTS |= gpiolowspeed | gpioaf | gpiopushpulltype | gpionopulltype; | ||||
gpiosetconfig(&CTS); | ||||
GPIO_PinAFConfig(GPIOGETPORT(CTS), (uint8_t)(CTS & 0xF), gpioAFuartx); | ||||
} | ||||
if(RTSpin!=-1) | ||||
{ | ||||
RTS = gpioopen(RTSpin); | ||||
RTS |= gpiolowspeed | gpioaf | gpiopushpulltype | gpionopulltype; | ||||
gpiosetconfig(&RTS); | ||||
GPIO_PinAFConfig(GPIOGETPORT(RTS), (uint8_t)(RTS & 0xF), gpioAFuartx); | ||||
} | ||||
} | ||||
return 1; | ||||
|
r14 | } | ||
|
r16 | int uartsetconfig(uart_t* uart) | ||
|
r14 | { | ||
|
r18 | int res=1; | ||
uartdisable(uart); | ||||
uartsetspeed(uart,uart->speed); | ||||
uartsetparity(uart,uart->cfg & UARTPARITYMASK); | ||||
uartsetdatabits(uart,uart->cfg & UARTBITSMASK); | ||||
uartsetstopbits(uart,uart->cfg & UARTSTOPBITSMASK); | ||||
uartenable(uart); | ||||
return res; | ||||
|
r14 | } | ||
|
r16 | int uartenable(uart_t* uart) | ||
|
r14 | { | ||
|
r18 | ((USART_TypeDef *)(uart->_dev))->CR1 |= (1<<13); | ||
((USART_TypeDef *)(uart->_dev))->CR1 |= (1<<2) + (1<<3); | ||||
((USART_TypeDef *)(uart->_dev))->DR = ' '; | ||||
return 1; | ||||
|
r16 | } | ||
int uartdisable(uart_t* uart) | ||||
{ | ||||
|
r18 | if((((USART_TypeDef *)(uart->_dev))->CR1 & ((1<<3) +(1<<13)))==((1<<3) +(1<<13))) | ||
{ | ||||
while((((USART_TypeDef *)(uart->_dev))->SR & (uint16_t)(1<<7))!=(uint16_t)(1<<7)); | ||||
} | ||||
((USART_TypeDef *)(uart->_dev))->CR1 &= ~((1<<2) + (1<<3) +(1<<13)); | ||||
return 1; | ||||
|
r14 | } | ||
|
r16 | int uartsetspeed(uart_t* uart,int speed) | ||
|
r14 | { | ||
|
r18 | uart->speed = speed; | ||
uint32_t tmpreg = 0x00, apbclock = 0x00; | ||||
uint32_t integerdivider = 0x00; | ||||
uint32_t fractionaldivider = 0x00; | ||||
RCC_ClocksTypeDef RCC_ClocksStatus; | ||||
RCC_GetClocksFreq(&RCC_ClocksStatus); | ||||
|
r16 | |||
|
r18 | if (((USART_TypeDef *)(uart->_dev) == USART1) || (((USART_TypeDef *)(uart->_dev) == USART6))) | ||
{ | ||||
apbclock = RCC_ClocksStatus.PCLK2_Frequency; | ||||
} | ||||
else | ||||
{ | ||||
apbclock = RCC_ClocksStatus.PCLK1_Frequency; | ||||
} | ||||
if (((((USART_TypeDef *)(uart->_dev))->CR1) & USART_CR1_OVER8) != (uint16_t)0) | ||||
{ | ||||
integerdivider = ((25 * apbclock) / (2 * (speed))); | ||||
} | ||||
else | ||||
{ | ||||
integerdivider = ((25 * apbclock) / (4 * (speed))); | ||||
} | ||||
tmpreg = (integerdivider / 100) << 4; | ||||
fractionaldivider = integerdivider - (100 * (tmpreg >> 4)); | ||||
if ((((USART_TypeDef *)(uart->_dev))->CR1 & USART_CR1_OVER8) != (uint16_t)0) | ||||
{ | ||||
tmpreg |= ((((fractionaldivider * 8) + 50) / 100)) & ((uint8_t)0x07); | ||||
} | ||||
else | ||||
{ | ||||
tmpreg |= ((((fractionaldivider * 16) + 50) / 100)) & ((uint8_t)0x0F); | ||||
} | ||||
((USART_TypeDef *)(uart->_dev))->BRR = (uint16_t)tmpreg; | ||||
return 1; | ||||
|
r16 | } | ||
int uartsetparity(uart_t* uart,uartparity_t parity) | ||||
{ | ||||
|
r18 | uart->cfg &= ~(UARTPARITYMASK); | ||
uart->cfg |= parity; | ||||
((USART_TypeDef *)(uart->_dev))->CR1 &= ~(((1<<9)+(1<<10))); | ||||
switch(parity) | ||||
{ | ||||
case uartparityeven: | ||||
((USART_TypeDef *)(uart->_dev))->CR1 |= (1<<10); | ||||
break; | ||||
case uartparityodd: | ||||
((USART_TypeDef *)(uart->_dev))->CR1 |= (1<<10) + (1<<9); | ||||
break; | ||||
case uartparitynone: | ||||
break; | ||||
default : | ||||
return 0; | ||||
break; | ||||
} | ||||
return 1; | ||||
|
r14 | } | ||
|
r16 | int uartsetdatabits(uart_t* uart,uartbits_t databits) | ||
|
r14 | { | ||
|
r18 | uart->cfg &= ~UARTBITSMASK; | ||
uart->cfg |= databits; | ||||
((USART_TypeDef *)(uart->_dev))->CR1 &= ~(((1<<12))); | ||||
switch(databits) | ||||
{ | ||||
case uart7bits: | ||||
return 0; | ||||
break; | ||||
case uart8bits: | ||||
break; | ||||
case uart9bits: | ||||
((USART_TypeDef *)(uart->_dev))->CR1 |= (1<<12); | ||||
break; | ||||
default : | ||||
return 0; | ||||
break; | ||||
} | ||||
return 1; | ||||
|
r16 | } | ||
int uartsetstopbits(uart_t* uart,uartstopbits_t stopbits) | ||||
{ | ||||
|
r18 | uart->cfg &= ~UARTSTOPBITSMASK; | ||
uart->cfg |= stopbits; | ||||
((USART_TypeDef *)(uart->_dev))->CR2 &= ~(((1<<12)+(1<<13))); | ||||
switch(stopbits) | ||||
{ | ||||
case uarthalfstop: | ||||
((USART_TypeDef *)(uart->_dev))->CR2 |= (1<<12); | ||||
break; | ||||
case uartonestop: | ||||
break; | ||||
case uartonehalfstop: | ||||
((USART_TypeDef *)(uart->_dev))->CR2 |= (1<<12) + (1<<13); | ||||
break; | ||||
case uarttwostop: | ||||
((USART_TypeDef *)(uart->_dev))->CR2 |= (1<<13); | ||||
break; | ||||
default : | ||||
return 0; | ||||
break; | ||||
} | ||||
return 1; | ||||
|
r14 | } | ||
|
r16 | int uartputc(uart_t* uart,char c) | ||
{ | ||||
|
r18 | while((((USART_TypeDef *)(uart->_dev))->SR & (uint16_t)(1<<7))!=(uint16_t)(1<<7)); | ||
((USART_TypeDef *)(uart->_dev))->DR = c; | ||||
return 1; | ||||
|
r16 | } | ||
char uartgetc(uart_t* uart) | ||||
|
r14 | { | ||
|
r18 | while(!(((USART_TypeDef *)(uart->_dev))->SR & (1<<5))); | ||
return (char)((USART_TypeDef *)(uart->_dev))->DR; | ||||
|
r16 | } | ||
int uartputs(uart_t* uart,char* s) | ||||
{ | ||||
|
r18 | while (*s) uartputc(uart,*s++); | ||
return 1; | ||||
|
r14 | } | ||
|
r16 | int uartgets(uart_t* uart,char* s) | ||
{ | ||||
|
r18 | do | ||
{ | ||||
(*s) = uartgetc(uart); | ||||
} | ||||
while(*s++); | ||||
return 1; | ||||
|
r16 | } | ||
int uartputnc(uart_t* uart,char* c,int n) | ||||
{ | ||||
|
r18 | int l=0; | ||
while(l<n) | ||||
{ | ||||
uartputc(uart,*c++); | ||||
l++; | ||||
} | ||||
return n; | ||||
|
r16 | } | ||
int uartgetnc(uart_t* uart,char* c,int n) | ||||
{ | ||||
|
r18 | int l=0; | ||
while(l<n) | ||||
{ | ||||
*c++=uartgetc(uart); | ||||
l++; | ||||
} | ||||
return n; | ||||
|
r16 | } | ||
int uartavailiabledata(uart_t* uart) | ||||
{ | ||||
|
r18 | if(!(((USART_TypeDef *)(uart->_dev))->SR & (1<<5))) | ||
return 0; | ||||
else | ||||
return 1; | ||||
} | ||||
int _uartstrwrite(streamdevice* device,void* data,int size, int n) | ||||
{ | ||||
return uartputnc((uart_t*) device->_stream,(char*) data,size*n); | ||||
} | ||||
int _uartstrread(streamdevice* device,void* data,int size, int n) | ||||
{ | ||||
return uartgetnc((uart_t*) device->_stream,(char*) data,size*n); | ||||
} | ||||
int _uartstrsetpos(streamdevice* device,int pos) | ||||
{ | ||||
return 1; | ||||
} | ||||
int uartmkstreamdev(uart_t* uart,streamdevice* strdev) | ||||
{ | ||||
strdev->_stream = (UHANDLE)uart; | ||||
strdev->write = (write_t)&_uartstrwrite; | ||||
strdev->read = (read_t)&_uartstrread; | ||||
strdev->setpos = (setpos_t)&_uartstrsetpos; | ||||
strdev->streamPt = 0; | ||||
return 1; | ||||
|
r14 | } | ||