1 | /*
|
2 | * Prototyp_1.c
|
3 | *
|
4 | * Created: 30.01.2020 11:07:41
|
5 | * Author : i2c
|
6 | */
|
7 |
|
8 |
|
9 | #include "sam.h"
|
10 | #include <stdbool.h>
|
11 |
|
12 |
|
13 |
|
14 | #define CMD_DAC_DEVID 0b00000001
|
15 | #define SLAVE_ADDR_DAC 0x72
|
16 | #define BUF_SIZE 3
|
17 |
|
18 |
|
19 |
|
20 |
|
21 | uint8_t tx_buf[BUF_SIZE]={1,2,3};
|
22 | uint8_t rx_buf[BUF_SIZE];
|
23 | uint8_t i;
|
24 | volatile bool tx_done=false, rx_done=false;
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 | void clk_init(void)
|
31 | {
|
32 |
|
33 | // Clock von GCLK0 ausgeben auf PB14
|
34 | PORT->Group[1].PMUX[7].bit.PMUXE = 12; // Multiplex M
|
35 | PORT->Group[1].DIRSET.reg = PORT_PB14; // 48MHz ausgeben auf Portpin
|
36 | PORT->Group[1].PINCFG[14].reg = PORT_PINCFG_PMUXEN;
|
37 | GCLK->GENCTRL[0].reg = GCLK_GENCTRL_OE |
|
38 | GCLK_GENCTRL_GENEN;
|
39 |
|
40 | }
|
41 |
|
42 |
|
43 |
|
44 |
|
45 |
|
46 | void i2c_init(void)
|
47 | {
|
48 |
|
49 | //SERCOM4 Core mit Generic Clock Generator 0 verbinden und aktivieren
|
50 | GCLK->PCHCTRL[34].reg = GCLK_PCHCTRL_CHEN |
|
51 | GCLK_PCHCTRL_GEN_GCLK0;
|
52 |
|
53 | MCLK->APBDMASK.bit.SERCOM4_ = 1; // Main-Clock auf SERCOM4 aktivieren
|
54 |
|
55 |
|
56 | SERCOM4->I2CM.CTRLA.bit.SWRST = 1; // Softwarereset für SERCOM4
|
57 | while(SERCOM4->I2CM.CTRLA.bit.SWRST | SERCOM4->I2CM.SYNCBUSY.bit.SWRST); // warten bis reset fertig
|
58 |
|
59 | SERCOM4->I2CM.CTRLA.reg = SERCOM_I2CM_CTRLA_MODE(5) | // muss Wert 5 haben in Master-Config
|
60 | SERCOM_I2CM_CTRLA_INACTOUT(1); // 55US Inactive Time-Out
|
61 |
|
62 | SERCOM4->I2CM.CTRLB.reg = SERCOM_I2CM_CTRLB_SMEN;
|
63 | while(SERCOM4->I2CM.SYNCBUSY.bit.SYSOP);
|
64 |
|
65 | //SERCOM4->I2CM.CTRLC.reg = SERCOM_I2CM_CTRLC_DATA32B; // Dataregister mit 32 Bit beschreiben
|
66 |
|
67 | SERCOM4->I2CM.BAUD.reg = 59; // Baudrate (400kb/s)
|
68 | while(SERCOM4->I2CM.SYNCBUSY.bit.SYSOP);
|
69 |
|
70 | SERCOM4->I2CM.INTENSET.reg = SERCOM_I2CM_INTENSET_MB | SERCOM_I2CM_INTENSET_SB; // Interrupt
|
71 |
|
72 | SERCOM4->I2CM.STATUS.reg = SERCOM_I2CM_STATUS_BUSSTATE(1);
|
73 | while(SERCOM4->I2CM.SYNCBUSY.bit.SYSOP);
|
74 |
|
75 | SERCOM4->I2CM.CTRLA.reg = SERCOM_I2CM_CTRLA_ENABLE; // Aktivieren
|
76 | while(SERCOM4->I2CM.SYNCBUSY.bit.ENABLE);
|
77 |
|
78 |
|
79 | PORT->Group[1].PMUX[4].bit.PMUXO = 3;
|
80 | PORT->Group[1].PMUX[4].bit.PMUXE = 3;
|
81 |
|
82 | PORT->Group[1].PINCFG[8].reg = PORT_PINCFG_PMUXEN;
|
83 | PORT->Group[1].PINCFG[9].reg = PORT_PINCFG_PMUXEN;
|
84 |
|
85 |
|
86 | NVIC_DisableIRQ(SERCOM4_2_IRQn);
|
87 | NVIC_ClearPendingIRQ(SERCOM4_2_IRQn);
|
88 | NVIC_SetPriority(SERCOM4_2_IRQn, 0);
|
89 | NVIC_EnableIRQ(SERCOM4_2_IRQn);
|
90 |
|
91 |
|
92 |
|
93 | }
|
94 |
|
95 |
|
96 |
|
97 |
|
98 |
|
99 |
|
100 |
|
101 | void SERCOM4_Handler(void)
|
102 | {
|
103 |
|
104 | /* Master on bus interrupt checking */
|
105 | if(SERCOM4->I2CM.INTFLAG.bit.MB)
|
106 | {
|
107 | if(i==BUF_SIZE)
|
108 | {
|
109 | /* After transferring the last byte stop condition will be sent */
|
110 | SERCOM4->I2CM.CTRLB.bit.CMD = 0x3;
|
111 | while(SERCOM4->I2CM.SYNCBUSY.bit.SYSOP);
|
112 | tx_done=true;
|
113 | i=0;
|
114 | }else
|
115 | {
|
116 | /* placing the data from transmitting buffer to DATA register*/
|
117 | SERCOM4->I2CM.DATA.reg = tx_buf[i++];
|
118 | while(SERCOM4->I2CM.SYNCBUSY.bit.SYSOP);
|
119 | }
|
120 | }
|
121 |
|
122 | /* Slave on bus interrupt checking */
|
123 | if(SERCOM4->I2CM.INTFLAG.bit.SB)
|
124 | {
|
125 | if(i==(BUF_SIZE-1))
|
126 | {
|
127 | /* NACK should be sent before reading the last byte */
|
128 | SERCOM4->I2CM.CTRLB.reg|=SERCOM_I2CM_CTRLB_ACKACT;
|
129 | while(SERCOM4->I2CM.SYNCBUSY.bit.SYSOP);
|
130 |
|
131 | SERCOM4->I2CM.CTRLB.bit.CMD=0x3;
|
132 | while(SERCOM4->I2CM.SYNCBUSY.bit.SYSOP);
|
133 |
|
134 | rx_buf[i++]=SERCOM4->I2CM.DATA.reg;
|
135 | while(SERCOM4->I2CM.SYNCBUSY.bit.SYSOP);rx_done=true;
|
136 | }else
|
137 | {
|
138 | SERCOM4->I2CM.CTRLB.reg&=~SERCOM_I2CM_CTRLB_ACKACT;
|
139 | while(SERCOM4->I2CM.SYNCBUSY.bit.SYSOP);
|
140 |
|
141 | rx_buf[i++]=SERCOM4->I2CM.DATA.reg;
|
142 | while(SERCOM4->I2CM.SYNCBUSY.bit.SYSOP);
|
143 |
|
144 | /* sending ACK after reading each byte */
|
145 | SERCOM4->I2CM.CTRLB.bit.CMD=0x2;
|
146 | while(SERCOM4->I2CM.SYNCBUSY.bit.SYSOP);
|
147 | }
|
148 | }
|
149 |
|
150 |
|
151 | }
|
152 |
|
153 |
|
154 |
|
155 |
|
156 | void i2c_master_transact(void)
|
157 | {
|
158 | i=0;
|
159 |
|
160 | /* Acknowledge section is set as ACKsignal by writing 0 in ACKACT bit */
|
161 | SERCOM4->I2CM.CTRLB.reg &= ~SERCOM_I2CM_CTRLB_ACKACT;
|
162 | while(SERCOM4->I2CM.SYNCBUSY.bit.SYSOP);
|
163 |
|
164 | /* slave address with Write(0) */
|
165 | SERCOM4->I2CM.ADDR.reg = (SLAVE_ADDR_DAC<<1) | 0;
|
166 | while(!tx_done);
|
167 |
|
168 | i=0;
|
169 |
|
170 | /* Acknowledge section is set as ACK signal by writing 0 in ACKACT bit */
|
171 | SERCOM4->I2CM.CTRLB.reg &= ~SERCOM_I2CM_CTRLB_ACKACT;
|
172 | while(SERCOM4->I2CM.SYNCBUSY.bit.SYSOP);
|
173 |
|
174 | /* slave address with read (1) */
|
175 | SERCOM4->I2CM.ADDR.reg = (SLAVE_ADDR_DAC<<1) | 1;
|
176 | while(!rx_done);
|
177 |
|
178 | /*interrupts are cleared */
|
179 | SERCOM4->I2CM.INTENCLR.reg = SERCOM_I2CM_INTENCLR_MB | SERCOM_I2CM_INTENCLR_SB;
|
180 |
|
181 | }
|
182 |
|
183 |
|
184 |
|
185 |
|
186 |
|
187 |
|
188 | void sleep(uint32_t count)
|
189 | {
|
190 | for(;count>0;count--)
|
191 | {
|
192 | asm volatile("NOP");
|
193 | }
|
194 | }
|
195 |
|
196 |
|
197 |
|
198 |
|
199 |
|
200 |
|
201 |
|
202 |
|
203 |
|
204 |
|
205 |
|
206 | int main(void)
|
207 | {
|
208 |
|
209 | __enable_irq();
|
210 |
|
211 | clk_init();
|
212 |
|
213 |
|
214 | i2c_init();
|
215 |
|
216 |
|
217 |
|
218 |
|
219 | while (1)
|
220 | {
|
221 |
|
222 | i2c_master_transact();
|
223 |
|
224 |
|
225 |
|
226 | sleep(500);
|
227 |
|
228 |
|
229 |
|
230 | }
|
231 | }
|