-
Notifications
You must be signed in to change notification settings - Fork 9
/
main.cpp
158 lines (139 loc) · 4.2 KB
/
main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/*
* math calculator i2c slave stm32
* Copyright (C) 2018 Amitesh Singh <[email protected]>
*
* 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, see <http://www.gnu.org/licenses/>.
*/
extern "C"
{
#include <libopencm3/cm3/common.h>
#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/gpio.h>
#include <libopencm3/stm32/i2c.h>
#include <libopencm3/cm3/nvic.h>
}
static void
my_delay_1( void )
{
int i = 72e6/2/4;
while( i > 0 )
{
i--;
__asm__( "nop" );
}
}
#define MYSLAVE_ADDRESS 0x32
//Set Commands
#define MYSLAVE_SET_REG 0x01
//GET commands
#define MYSLAVE_GET_ADD_RESULT 0x02
#define MYSLAVE_GET_SUB_RESULT 0x03
#define MYSLAVE_GET_MUL_RESULT 0x04
static void
i2c_slave_init(uint8_t ownaddress)
{
rcc_periph_clock_enable(RCC_GPIOB);
rcc_periph_clock_enable(RCC_I2C1);
nvic_enable_irq(NVIC_I2C1_EV_IRQ);
// configure i2c pins
gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_OPENDRAIN,
GPIO_I2C1_SDA); //PB7
gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_OPENDRAIN,
GPIO_I2C1_SCL); //PB6
i2c_peripheral_disable(I2C1);
i2c_set_speed(I2C1, i2c_speed_sm_100k, 36);
i2c_set_own_7bit_slave_address(I2C1, ownaddress);
i2c_enable_interrupt(I2C1, I2C_CR2_ITEVTEN | I2C_CR2_ITBUFEN);
i2c_peripheral_enable(I2C1);
// slave needs to acknowledge on receiving bytes
// set it after enabling Peripheral i.e. PE = 1
i2c_enable_ack(I2C1);
}
volatile uint8_t *read_p;
volatile uint8_t *write_p;
volatile uint8_t writing;
volatile uint8_t reading;
volatile uint8_t buf[3];
volatile uint16_t val;
//i2c1 event ISR
extern "C" void i2c1_ev_isr(void)
{
uint32_t sr1, sr2;
sr1 = I2C_SR1(I2C1);
// Address matched (Slave)
if (sr1 & I2C_SR1_ADDR)
{
reading = 0;
read_p = buf;
write_p = ((volatile uint8_t *)(&val) + 1);
writing = 2;
//Clear the ADDR sequence by reading SR2.
sr2 = I2C_SR2(I2C1);
(void) sr2;
}
// Receive buffer not empty
else if (sr1 & I2C_SR1_RxNE)
{
//ignore more than 3 bytes reading
if (reading > 3)
return;
//read bytes from slave
*read_p++ = i2c_get_data(I2C1);
reading++;
}
// Transmit buffer empty & Data byte transfer not finished
else if ((sr1 & I2C_SR1_TxE) && !(sr1 & I2C_SR1_BTF))
{
//send data to master in MSB order
i2c_send_data(I2C1, *write_p--);
writing--;
}
// done by master by sending STOP
//this event happens when slave is in Recv mode at the end of communication
else if (sr1 & I2C_SR1_STOPF)
{
i2c_peripheral_enable(I2C1);
if (buf[0] == MYSLAVE_GET_ADD_RESULT)
val = buf[1] + buf[2];
else if (buf[0] == MYSLAVE_GET_SUB_RESULT)
val = buf[1] - buf[2];
else if (buf[0] == MYSLAVE_GET_MUL_RESULT)
val = buf[1] * buf[2];
}
//this event happens when slave is in transmit mode at the end of communication
else if (sr1 & I2C_SR1_AF)
{
//(void) I2C_SR1(I2C1);
I2C_SR1(I2C1) &= ~(I2C_SR1_AF);
}
}
int main( void )
{
//set STM32 to 72 MHz
rcc_clock_setup_pll(&rcc_hse_configs[RCC_CLOCK_HSE8_72MHZ]);
// Enable GPIOC clock
rcc_periph_clock_enable(RCC_GPIOC);
//Set GPIO13 (inbuild led connected) to 'output push-pull'
gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL,
GPIO13);
//switch led off
gpio_set(GPIOC, GPIO13);
//initialize i2c slave
i2c_slave_init(MYSLAVE_ADDRESS);
while( 1 )
{
gpio_toggle(GPIOC, GPIO13);
my_delay_1();
}
}