#include "stm32f4xx.h"
#include "stm32f4xx_usart.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_i2c.h"
#include "misc.h"
#include "stdlib.h"
#include "math.h"
void Delay(__IO uint32_t nCount)
{
while(nCount--)
{
}
}
//the function “I2C_Write1Byte” to send one byte of data into the slave to a given address is presented next.
//The function receives three arguments for defining the address of the slave (‘SlaveAddr’),
//selecting the register within the slave (‘addr’) and the data to be sent to this register (‘byte1’);
void I2C_Write1Byte(u8 SlaveAddr, char addr, char byte1)
{
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY)); //WAIT IF I2C1 IS BUSY
I2C_GenerateSTART(I2C1, ENABLE); //GENERATE START
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); //WAIT FOR EV5
I2C_Send7bitAddress(I2C1, (SlaveAddr << 1), I2C_Direction_Transmitter); //SEND SLAVE ADDRESS
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); //WAIT FOR EV6
I2C_SendData(I2C1, addr); //ADDRESS WITHIN SLAVE
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING)); //WAIT FOR EV8
I2C_SendData(I2C1, byte1); //SEND DATA TO SLAVE
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); //WAIT FOR EV8_2
I2C_GenerateSTOP(I2C1, ENABLE); //GENERATE STOP
}
//and the function “I2C_Read1Byte” to read one byte of data from slave is presented next.
//The function receives two arguments for defining the address of the slave (‘SlaveAddr’), and selecting the register within the slave (‘addr’);
char I2C_Read1Byte(char SlaveAddr, char addr)
{
//FORST 6 LINES FOR SENDING ADDRESS WITHIN SLAVE
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY)); //WAIT IF I2C1 IS BUSY
I2C_GenerateSTART(I2C1, ENABLE); //GENERATES START
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); //WAIT FOR EV5
I2C_Send7bitAddress(I2C1, (SlaveAddr << 1), I2C_Direction_Transmitter); //SEND DEVICE ADDRESS BUT WE ARE WRITING
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); //WAIT FOR EV6
I2C_SendData(I2C1, addr); //addr WITHIN DEVICE
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); //WAIT FOR EV8_2
//UPCOMING LINES FOR READING DATA FROM DR "DATA REGISTER"
I2C_GenerateSTART(I2C1, ENABLE); //GENERATE START
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); //WAIT FOR EV5
I2C_Send7bitAddress(I2C1, (SlaveAddr << 1), I2C_Direction_Receiver); //SEND DEVICE ADDRESS BUT WE ARE READING
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)); //WAIT FOR EV6
/* If more than one byte is to be read from the slave, then the last part of the function following line 13 should be replaced by the listing below.
*
* I2C_AcknowledgeConfig(I2C1, ENABLE); // acknowledge 1st byte
* while( !I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED) ); // wait EV7
* char byte1 = I2C_ReceiveData(I2C1); // retrieve byte
* I2C_AcknowledgeConfig(I2C1, DISABLE); // do not acknowledge 2nd byte
* while( !I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED) );
* char byte2 = I2C_ReceiveData(I2C1);// retrieve byte
* I2C_GenerateSTOP(I2C1, ENABLE); // generate STOP
* return ((byte2 << 8) + byte1);
*
*/
I2C_AcknowledgeConfig(I2C1, DISABLE); //DO NOT ACK
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED)); //WAIT FOR EV7
char byte1 = I2C_ReceiveData(I2C1); //RETRIEVE BYTE
I2C_GenerateSTOP(I2C1, ENABLE); //GENERATE STOP
return (byte1);
}
uint16_t I2C_Read2Byte(char SlaveAddr, char addr)
{
//FORST 6 LINES FOR SENDING ADDRESS WITHIN SLAVE
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY)); //WAIT IF I2C1 IS BUSY
I2C_GenerateSTART(I2C1, ENABLE); //GENERATES START
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); //WAIT FOR EV5
I2C_Send7bitAddress(I2C1, (SlaveAddr << 1), I2C_Direction_Transmitter); //SEND DEVICE ADDRESS BUT WE ARE WRITING
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); //WAIT FOR EV6
I2C_SendData(I2C1, addr); //addr WITHIN DEVICE
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); //WAIT FOR EV8_2
//UPCOMING LINES FOR READING DATA FROM DR "DATA REGISTER"
I2C_GenerateSTART(I2C1, ENABLE); //GENERATE START
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); //WAIT FOR EV5
I2C_Send7bitAddress(I2C1, (SlaveAddr << 1), I2C_Direction_Receiver); //SEND DEVICE ADDRESS BUT WE ARE READING
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)); //WAIT FOR EV6
I2C_AcknowledgeConfig(I2C1, ENABLE); // acknowledge 1st byte
while( !I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED) ); // wait EV7
char byte1 = I2C_ReceiveData(I2C1); // retrieve byte
I2C_AcknowledgeConfig(I2C1, DISABLE); // do not acknowledge 2nd byte
while( !I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED) );
char byte2 = I2C_ReceiveData(I2C1);// retrieve byte
I2C_GenerateSTOP(I2C1, ENABLE); // generate STOP
return ((byte2 << 8) | byte1);
}
void setup_Pheriph()
{
GPIO_InitTypeDef GPIO_InitStruct;
USART_InitTypeDef USART_InitStruct;
NVIC_InitTypeDef NVIC_InitStruct;
I2C_InitTypeDef I2C_InitStruct;
//ENABLE PERIPH CLOCK FOR USART2
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
//ENABLE GPIOA CLOCK
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
//ENABLE GPIOD CLOCK
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
//ENABLE GPIOB CLOCK
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
//ENABLE I2C1 CLOCK
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
//SETUP GPIOA PINS FOR USART Tx AND Rx
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; //SINCE WE HAVE USED ALTERNATIVE FUNCTION WE SHOULD ASIGN IT DOWN
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_25MHz;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; //PULL UP RESISTORS
GPIO_Init(GPIOA, &GPIO_InitStruct);
//SETTING UP AF FOR UARTS2
GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2); //WE SET PIN2 AND 3 AS AF FOR UART2
GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART2);
//SETUP GPIOD PINS FOR BLINKING LED
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13 |GPIO_Pin_12 |GPIO_Pin_14|GPIO_Pin_15;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_25MHz;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_Init(GPIOD, &GPIO_InitStruct);
//SETUP GPIO FOR I2C SCL AND SDL
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; //SDA, SCL DEF
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_OType = GPIO_OType_OD;
GPIO_Init(GPIOB, &GPIO_InitStruct);
//SETTING UP AF FOR I2C
GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_I2C1);
//SETUP USART CONFIG
USART_InitStruct.USART_BaudRate = 9600;
USART_InitStruct.USART_WordLength = USART_WordLength_8b;
USART_InitStruct.USART_StopBits = USART_StopBits_1;
USART_InitStruct.USART_Parity = USART_Parity_No;
USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; //WE SETUP USART FOR Rx AND Tx
USART_Init(USART2, &USART_InitStruct);
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); //SETUP INTERRUPT REQUEST FOR USART FOR ONLY RECEIVE
//SETTING UP INTERRUPT REQUEST NVIC
NVIC_InitStruct.NVIC_IRQChannel = USART2_IRQn; //CHANNEL IS THE INTERRUPT NAME I WANT TO CONFIGURE
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; //ENABLE USART GLOBALLY
NVIC_Init(&NVIC_InitStruct);
//ENABLE USART2 PERIPHERAL
USART_Cmd(USART2, ENABLE);
//SETTING UP I2C CONFIG
I2C_InitStruct.I2C_ClockSpeed = 100000;
I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;
I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_16_9;
I2C_InitStruct.I2C_OwnAddress1 = 0; //GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1);
I2C_InitStruct.I2C_Ack = I2C_Ack_Disable; //
I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_Init(I2C1, &I2C_InitStruct);
I2C_Cmd(I2C1, ENABLE);
}
void USART_putch(USART_TypeDef* USARTx, uint8_t ch)
{
USART_SendData(USARTx,ch);
while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET);
}
void USART_puts(USART_TypeDef* USARTx, uint8_t str[])
{
while(*str) USART_putch(USARTx, *str++);
}
void USART_PutNumber(USART_TypeDef* USARTx, uint32_t x)
{
char value[20]; //a temp array to hold results of conversion
int i = 0; //loop index
do
{
value[i++] = (char)(x % 10) + '0'; //convert integer to character
x /= 10;
} while(x);
while(i) //send data
{
USART_putch(USARTx, value[--i]);
}
USART_puts(USARTx, " \r\n");
}
void USART_Float(USART_TypeDef *USARTx, float x)
{
char str[80];
sprintf(str, "%.02f", x);
USART_putch(USARTx, str);
}
uint16_t USART_receive_char(USART_TypeDef *USARTx)
{
//WAIT UNTIL CHAR IS RECEIVED
while(!USART_GetFlagStatus(USARTx, USART_FLAG_RXNE));
//READ RECEIVED CHAR
return USART_ReceiveData(USARTx);
}
int main(void)
{
setup_Pheriph();
USART_puts(USART2, "Welcome Mohamed!\r\n");
//USART_PutNumber(USART2, 2313);
I2C_Write1Byte(0x68, 0x6B, 0);
I2C_Write1Byte(0x68, 0x1C, 0);
while(1)
{
// a test to read accelerometer x axis
uint16_t byte = (I2C_Read1Byte(0x68, 0x3B)<<8)|(I2C_Read1Byte(0x68, 0x3C));
(float)byte = byte/16384.0;
USART_Float(USART2, byte);
Delay(16800000);
}
}
uint16_t rec_char;
void USART2_IRQHandler()
{
rec_char = USART_receive_char(USART2);
if(rec_char == 'o')
GPIO_WriteBit(GPIOD, GPIO_Pin_13, Bit_SET);
if(rec_char == 'g')
GPIO_WriteBit(GPIOD, GPIO_Pin_12, Bit_SET);
if(rec_char == 'r')
GPIO_WriteBit(GPIOD, GPIO_Pin_14, Bit_SET);
if(rec_char == 'b')
GPIO_WriteBit(GPIOD, GPIO_Pin_15, Bit_SET);
if(rec_char == 'x')
GPIO_WriteBit(GPIOD, GPIO_Pin_13 |GPIO_Pin_12 |GPIO_Pin_14|GPIO_Pin_15, Bit_RESET);
}