kopia lustrzana https://github.com/SP8EBC/ParaTNC
247 wiersze
7.6 KiB
C
247 wiersze
7.6 KiB
C
#include "drivers/i2c.h"
|
||
#include "drivers/gpio_conf.h"
|
||
#include <stm32f10x.h>
|
||
|
||
int i2cPinRemap = 0;
|
||
//int i2cClockSpeed = 8; // w realu tu powinno by<62> 5 przy moich ustawieniach zegara
|
||
int i2cClockSpeed = 5;
|
||
int i2cCCRegisterValue = 0x78;
|
||
//int i2cRiseRegisterValue = 0x09; // w realu 6
|
||
int i2cRiseRegisterValue = 0x06;
|
||
|
||
volatile uint16_t i2cRemoteAddr = 0; // adres zdalnego urz<72>dzenia
|
||
volatile uint8_t i2cTXData[32] = {'\0'}; // dane do wys<79>ania do zdalnego urz<72>dzenia
|
||
volatile uint8_t i2cRXData[32] = {'\0'}; // dane odebrane od zdalnego urz<72>dzenia
|
||
volatile uint8_t i2cRXing = 0; // ustawiony na 1 kiedy trwa odbi<62>r danych
|
||
volatile uint8_t i2cTXing = 0; // ustawiony na 1 kiedy trwa wysy<73>anie danych
|
||
volatile uint8_t i2cDone = 0; // ustawiany na jeden w momencie zako<6B>czenia wysy<73>ania/odbioru
|
||
volatile uint8_t i2cTXQueueLen = 0; // liczba bajt<6A>w w kolejce do wys<79>ania
|
||
volatile uint8_t i2cTRXDataCounter = 0; // licznik odebranych/wyslanych danych
|
||
volatile uint8_t i2cRXBytesNumber = 0; // liczba bajtow do odebrania
|
||
volatile uint8_t i2cErrorCounter = 0; // liczbnik b<><62>d<EFBFBD>w transmisji
|
||
|
||
volatile enum i2c_state i2c_state;
|
||
|
||
#define MAX_I2C_ERRORS_PER_COMM 5
|
||
|
||
void i2cConfigure() { // funkcja konfiguruje pierwszy kontroler i2c!!!
|
||
I2C_InitTypeDef I2C_InitStructure;
|
||
|
||
RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; // w<><77>czenie zegara dla i2c
|
||
NVIC_EnableIRQ( I2C1_EV_IRQn ); // w<><77>czenie w kontrolerze przerwan
|
||
NVIC_EnableIRQ( I2C1_ER_IRQn );
|
||
DBGMCU->CR |= DBGMCU_CR_DBG_I2C1_SMBUS_TIMEOUT; // wy<77><79>czanie timeout<75>w podczas debugowania
|
||
if (i2cPinRemap == 0) {
|
||
Configure_GPIO(GPIOB,6,AFOD_OUTPUT_2MHZ); //SCL
|
||
Configure_GPIO(GPIOB,7,AFOD_OUTPUT_2MHZ); //SDA
|
||
}
|
||
else {
|
||
AFIO->MAPR |= AFIO_MAPR_I2C1_REMAP;
|
||
Configure_GPIO(GPIOB,8,AFOD_OUTPUT_2MHZ);
|
||
Configure_GPIO(GPIOB,9,AFOD_OUTPUT_2MHZ);
|
||
}
|
||
// NVIC->IP[31] = 0x55;
|
||
NVIC_SetPriority(I2C1_EV_IRQn, 1);
|
||
|
||
I2C_StructInit(&I2C_InitStructure);
|
||
|
||
/* Konfiguracja I2C */
|
||
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
|
||
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
|
||
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
|
||
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
|
||
I2C_InitStructure.I2C_ClockSpeed = 50000;
|
||
|
||
/* Potwierdzamy konfigurację przed włączeniem I2C */
|
||
I2C_Init(I2C1, &I2C_InitStructure);
|
||
|
||
/* Włączenie I2C */
|
||
I2C_Cmd(I2C1, ENABLE);
|
||
|
||
I2C1->CR2 |= I2C_CR2_ITEVTEN; // w<><77>czenie generowanie przerwania od zdarzen i2c
|
||
I2C1->CR2 |= I2C_CR2_ITBUFEN;
|
||
I2C1->CR2 |= I2C_CR2_ITERREN;
|
||
|
||
}
|
||
|
||
int i2cSendData(int addr, int* data, int null) {
|
||
int i;
|
||
for (i = 0; (i<32 && *(data+i) != '\0'); i++)
|
||
i2cTXData[i]=data[i];
|
||
if (null == 0x01) { // je<6A>eli do slave trzeba wys<79>a<EFBFBD> 0x00
|
||
i2cTXData[0] = 0x00;
|
||
i = 1;
|
||
}
|
||
i2cTXQueueLen = i;
|
||
i2cRemoteAddr = addr;
|
||
|
||
i2cTXing = 1;
|
||
i2cErrorCounter = 0;
|
||
I2C_Cmd(I2C1, ENABLE);
|
||
|
||
NVIC_EnableIRQ( I2C1_EV_IRQn ); // w<><77>czenie w kontrolerze przerwan
|
||
NVIC_EnableIRQ( I2C1_ER_IRQn );
|
||
|
||
I2C1->CR1 |= I2C_CR1_START; // zadanie warunkow startowych
|
||
return 0;
|
||
}
|
||
|
||
int i2cReceiveData(int addr, int* data, int num) {
|
||
i2cRXBytesNumber = num;
|
||
i2cRemoteAddr = addr;
|
||
i2cTRXDataCounter = 0;
|
||
i2cRXing = 1;
|
||
I2C_Cmd(I2C1, ENABLE);
|
||
|
||
NVIC_EnableIRQ( I2C1_EV_IRQn ); // w<><77>czenie w kontrolerze przerwan
|
||
NVIC_EnableIRQ( I2C1_ER_IRQn );
|
||
|
||
I2C1->CR1 |= I2C_CR1_START; // zadanie warunkow startowych
|
||
return 0;
|
||
}
|
||
|
||
|
||
|
||
void i2cVariableReset(void) {
|
||
I2C1->DR = 0x00;
|
||
i2cTRXDataCounter = 0;
|
||
i2cTXQueueLen = 0;
|
||
i2cRXBytesNumber = 0;
|
||
}
|
||
|
||
void i2cIrqHandler(void) {
|
||
// int i;
|
||
if ((I2C1->SR1 & I2C_SR1_SB) == I2C_SR1_SB && (i2cTXing == 1 || i2cRXing == 1)) {
|
||
// po nadaniu warunk<6E>w startu podczas wysy<73>ania danych do slave EV5
|
||
I2C1->DR = i2cRemoteAddr; // wpisanie do DR adresu slave do nadania
|
||
I2C1->SR1 &= (0xFFFFFFFF ^ I2C_SR1_SB); // gaszenie flagi SB
|
||
|
||
|
||
|
||
// I2C1->SR1 & I2C_SR1_SB;
|
||
|
||
}
|
||
if ((I2C1->SR1 & I2C_SR1_ADDR) == I2C_SR1_ADDR && (i2cTXing == 1 || i2cRXing == 1)) {
|
||
// po wys<79>aniu adresu slave EV6
|
||
I2C1->SR1 &= (0xFFFFFFFF ^ I2C_SR1_ADDR);
|
||
I2C1->SR2 &= (0xFFFFFFFF ^ I2C_SR2_TRA);
|
||
|
||
if (i2cRXBytesNumber == 1 && i2cRXing == 1) {
|
||
/// EV_6_1
|
||
I2C1->CR1 &= (0xFFFFFFFF ^ I2C_CR1_ACK); // wy<77>czanie odpowiadania ACK przy odbiorze je<6A>eli tylko 1 bjt
|
||
I2C1->CR1 |= I2C_CR1_STOP;
|
||
}
|
||
|
||
if (i2cRXing == 1)
|
||
I2C1->CR1 |= I2C_CR1_ACK; // ustawienie bity ACK
|
||
}
|
||
if ((I2C1->SR1 & I2C_SR1_TXE) == I2C_SR1_TXE && i2cTXing == 1) {
|
||
// EV_8_1
|
||
I2C1->DR = i2cTXData[0];
|
||
i2cTRXDataCounter++;
|
||
}
|
||
if (i2cTRXDataCounter == i2cTXQueueLen && i2cTXing == 1) {
|
||
// przes<65>ano wszystkie dane, czyli teraz trzeba da<64> warunki STOP
|
||
i2cTXing = 0;
|
||
I2C1->CR1 |= I2C_CR1_STOP;
|
||
while ((I2C1->CR1 & I2C_CR1_STOP) == I2C_CR1_STOP);
|
||
|
||
I2C_Cmd(I2C1, DISABLE);
|
||
|
||
i2cVariableReset();
|
||
}
|
||
if ((I2C1->SR1 & I2C_SR1_BTF) == I2C_SR1_BTF && i2cTXing == 1) {
|
||
// EV_8
|
||
if ((I2C1->SR1 & I2C_SR1_TXE) == I2C_SR1_TXE && i2cTXing == 1 && i2cTRXDataCounter < i2cTXQueueLen) {
|
||
I2C1->DR = i2cTXData[i2cTRXDataCounter];
|
||
i2cTRXDataCounter++;
|
||
I2C1->SR1 &= (0xFFFFFFFF ^ I2C_SR1_BTF);
|
||
}
|
||
}
|
||
if ((I2C1->SR1 & I2C_SR1_RXNE) == I2C_SR1_RXNE && i2cRXing == 1) {
|
||
// EV_7
|
||
*(i2cRXData + i2cTRXDataCounter) = I2C1->DR & I2C_DR_DR;
|
||
i2cTRXDataCounter++;
|
||
if (i2cRXBytesNumber-i2cTRXDataCounter == 1) {
|
||
I2C1->CR1 &= (0xFFFFFFFF ^ I2C_CR1_ACK); //jezeli odebrano przedostatni bajt to trzeba
|
||
// zgasic bit ACK zeby nastepnie wyslano NACK na koniec
|
||
}
|
||
if (i2cRXBytesNumber-i2cTRXDataCounter == 0) {
|
||
I2C1->CR1 |= I2C_CR1_STOP; // po odczytaniu z rejestru DR ostatniego bajtu w sekwencji
|
||
// nast<73>puje wys<79>anie warunk<6E>w STOP na magistrale
|
||
while ((I2C1->CR1 & I2C_CR1_STOP) == I2C_CR1_STOP);
|
||
i2cRXing = 0;
|
||
I2C_Cmd(I2C1, DISABLE);
|
||
*(i2cRXData + i2cTRXDataCounter) = '\0';
|
||
i2cVariableReset();
|
||
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|
||
void i2cErrIrqHandler(void) {
|
||
|
||
|
||
if (((I2C1->SR1 & I2C_SR1_AF) == I2C_SR1_AF) && i2cTRXDataCounter == 0 ) {
|
||
// slave nie odpowiedzia<69> ack na sw<73>j adres
|
||
I2C1->SR1 &= (0xFFFFFFFF ^ I2C_SR1_AF);
|
||
I2C1->CR1 |= I2C_CR1_STOP; // zadawanie warunkow STOP i przerywanie komunikacji
|
||
while ((I2C1->CR1 & I2C_CR1_STOP) == I2C_CR1_STOP);
|
||
i2cErrorCounter++; // zwieksza wartosc licznika b<><62>d<EFBFBD>w transmisji
|
||
I2C1->CR1 |= I2C_CR1_START; // ponawianie komunikacji
|
||
|
||
}
|
||
if (((I2C1->SR1 & I2C_SR1_AF) == I2C_SR1_AF) && i2cTRXDataCounter != 0 ) {
|
||
//jezeli slave nie odpowiedzia<69> ack na wys<79>any do niego bajt danych
|
||
I2C1->SR1 &= (0xFFFFFFFF ^ I2C_SR1_AF);
|
||
i2cErrorCounter++;
|
||
i2cTRXDataCounter--; // zmniejszanie warto<74>ci licznika danych aby nadac jeszcze raz to samo
|
||
|
||
}
|
||
|
||
if (((I2C1->SR1 & I2C_SR1_ARLO) == I2C_SR1_ARLO) ) {
|
||
|
||
i2cErrorCounter = MAX_I2C_ERRORS_PER_COMM + 1;
|
||
|
||
}
|
||
|
||
|
||
if (((I2C1->SR1 & I2C_SR1_TIMEOUT) == I2C_SR1_TIMEOUT) ) {
|
||
|
||
i2cErrorCounter = MAX_I2C_ERRORS_PER_COMM + 1;
|
||
|
||
}
|
||
|
||
if (((I2C1->SR1 & I2C_SR1_OVR) == I2C_SR1_OVR) ) {
|
||
|
||
i2cErrorCounter = MAX_I2C_ERRORS_PER_COMM + 1;
|
||
|
||
}
|
||
|
||
if (((I2C1->SR1 & I2C_SR1_BERR) == I2C_SR1_BERR) ) {
|
||
|
||
i2cErrorCounter = MAX_I2C_ERRORS_PER_COMM + 1;
|
||
|
||
}
|
||
|
||
// if this seems to be some unknow or unhalted error
|
||
i2cErrorCounter++;
|
||
|
||
if (i2cErrorCounter > MAX_I2C_ERRORS_PER_COMM) {
|
||
i2cRXing = 0;
|
||
i2cTXing = 0;
|
||
i2cTXQueueLen = 0;
|
||
i2cTRXDataCounter = 0;
|
||
i2cRXBytesNumber = 0;
|
||
|
||
I2C_Cmd(I2C1, DISABLE);
|
||
|
||
|
||
NVIC_DisableIRQ( I2C1_ER_IRQn );
|
||
NVIC_DisableIRQ( I2C1_EV_IRQn );
|
||
}
|
||
|
||
}
|