diff --git a/schematic/ALL.lst b/schematic/ALL.lst index aa8f3f1..299e9e8 100644 --- a/schematic/ALL.lst +++ b/schematic/ALL.lst @@ -1,70 +1,69 @@ -eeschema (2013-feb-26)-stable >> Creation date: Пн 21 июл 2014 08:49:29 #Cmp ( order = Reference ) -| C4 2200u, 40V -| C5 10u -| C6 100u -| C7 100n -| C8 100n -| C9 100n -| C10 27p -| C11 27p -| C12 100n -| C13 10u -| C14 100n -| C15 100n -| C16 100n -| C17 100n -| C18 100n -| C1.1 68n -| C1.2 68n -| C1.3 68n -| C1.4 68n -| C1.5 68n -| C2.1 1n -| C2.2 1n -| C2.3 1n -| C2.4 1n -| C2.5 1n -| C3.1 1n -| C3.2 1n -| C3.3 1n -| C3.4 1n -| C3.5 1n -| CON1 USB-MICRO-B -| DA1 IPS5451 -| DA2 TLE5205 -| DA4 USBLC6-2 -| DA5 RO-1224 +| C4 2200u, 40V +| C5 10u +| C6 100u +| C7 100n +| C8 100n +| C9 100n +| C10 27p +| C11 27p +| C12 100n +| C13 10u +| C14 100n +| C15 100n +| C16 100n +| C17 100n +| C18 100n +| C1.1 68n +| C1.2 68n +| C1.3 68n +| C1.4 68n +| C1.5 68n +| C2.1 1n +| C2.2 1n +| C2.3 1n +| C2.4 1n +| C2.5 1n +| C3.1 1n +| C3.2 1n +| C3.3 1n +| C3.4 1n +| C3.5 1n +| CON1 USB-MICRO-B +| DA1 IPS5451 +| DA2 TLE5205 +| DA4 USBLC6-2 +| DA5 RO-1224 | DA6 LM1117MPX-3.3 -| DD1 ADM233L -| DD3 STM32F103 -| DD2.1 L6208N -| DD2.2 L6208N -| DD2.3 L6208N -| DD2.4 L6208N -| DD2.5 L6208N -| G1 8MHz +| DD1 ADM233L +| DD3 STM32F103 +| DD2.1 L6208N +| DD2.2 L6208N +| DD2.3 L6208N +| DD2.4 L6208N +| DD2.5 L6208N +| G1 8MHz | L1 BMB2A0300AN1 -| R7 22k -| R8 15k -| R9 1.5k -| R10 510 -| R11 4.7k -| R12 1M -| R13 10k -| R14 10k -| R15 10k -| R16 10k -| R17 10k -| R18 100k -| R19 4.7k -| R20 15k -| R21 15k -| R22 10k -| R23 10k -| R24 10k -| R25 300 (II) -| R26 10k +| R7 22k +| R8 15k +| R9 1.5k +| R10 510 +| R11 4.7k +| R12 1M +| R13 10k +| R14 10k +| R15 10k +| R16 10k +| R17 10k +| R18 100k +| R19 4.7k +| R20 15k +| R21 15k +| R22 10k +| R23 10k +| R24 10k +| R25 300 (II) +| R26 10k | R27 RT0805BRB071KL | R28 RT0805BRB071KL | R29 RT0805BRB071KL @@ -73,188 +72,188 @@ eeschema (2013-feb-26)-stable >> Creation date: Пн 21 июл 2014 08:49:29 | R32 RT0805BRB071KL | R33 RT0805BRB071KL | R34 RT0805BRB071KL -| R35 22 -| R36 22 -| R37 10k -| R38 10k -| R39 10k -| R1.1 0.33 -| R1.2 0.33 -| R1.3 0.33 -| R1.4 0.33 -| R1.5 0.33 -| R2.1 0.33 -| R2.2 0.33 -| R2.3 0.33 -| R2.4 0.33 -| R2.5 0.33 -| R3.1 22k -| R3.2 22k -| R3.3 22k -| R3.4 22k -| R3.5 22k -| R4.1 1.8k -| R4.2 1.8k -| R4.3 1.8k -| R4.4 1.8k -| R4.5 1.8k -| R40.1 68 -| R40.2 68 -| R5.1 51k -| R5.2 51k -| R5.3 51k -| R5.4 51k -| R5.5 51k -| R6.1 51k -| R6.2 51k -| R6.3 51k -| R6.4 51k -| R6.5 51k -| SB1 RESET -| SB2 BOOT -| VD1 B120-E3 -| VD2 PWR -| VD3 B120-E3 -| VT1 DTA114Y -| VT2.1 NTE2984 -| VT2.2 NTE2984 -| XP1 GPRM1-61 -| XP2 TRD -| XP3 CONN_7 -| XP4 CONN_4 -| XP5 CONN_7 -| XP6 DB9 -| XP7 Power -| XS1 DB9 +| R35 22 +| R36 22 +| R37 10k +| R38 10k +| R39 10k +| R1.1 0.33 +| R1.2 0.33 +| R1.3 0.33 +| R1.4 0.33 +| R1.5 0.33 +| R2.1 0.33 +| R2.2 0.33 +| R2.3 0.33 +| R2.4 0.33 +| R2.5 0.33 +| R3.1 22k +| R3.2 22k +| R3.3 22k +| R3.4 22k +| R3.5 22k +| R4.1 1.8k +| R4.2 1.8k +| R4.3 1.8k +| R4.4 1.8k +| R4.5 1.8k +| R40.1 68 +| R40.2 68 +| R5.1 51k +| R5.2 51k +| R5.3 51k +| R5.4 51k +| R5.5 51k +| R6.1 51k +| R6.2 51k +| R6.3 51k +| R6.4 51k +| R6.5 51k +| SB1 RESET +| SB2 BOOT +| VD1 B120-E3 +| VD2 PWR +| VD3 B120-E3 +| VT1 DTA114Y +| VT2.1 NTE2984 +| VT2.2 NTE2984 +| XP1 GPRM1-61 +| XP2 TRD +| XP3 CONN_7 +| XP4 CONN_4 +| XP5 CONN_7 +| XP6 DB9 +| XP7 Power +| XS1 DB9 #End Cmp #Cmp ( order = Value ) -| 27p C10 -| 27p C11 -| 1n C2.1 -| 1n C2.2 -| 1n C2.3 -| 1n C2.4 -| 1n C2.5 -| 1n C3.1 -| 1n C3.2 -| 1n C3.3 -| 1n C3.4 -| 1n C3.5 -| 68n C1.1 -| 68n C1.2 -| 68n C1.3 -| 68n C1.4 -| 68n C1.5 -| 100n C7 -| 100n C8 -| 100n C9 -| 100n C12 -| 100n C14 -| 100n C15 -| 100n C16 -| 100n C17 -| 100n C18 -| 10u C5 -| 10u C13 -| 100u C6 -| 2200u, 40V C4 -| USB-MICRO-B CON1 -| RO-1224 DA5 -| LM1117MPX-3.3 DA6 -| USBLC6-2 DA4 -| IPS5451 DA1 -| TLE5205 DA2 -| ADM233L DD1 -| L6208N DD2.1 -| L6208N DD2.2 -| L6208N DD2.3 -| L6208N DD2.4 -| L6208N DD2.5 -| STM32F103 DD3 -| 8MHz G1 -| BMB2A0300AN1 L1 -| 0.33 R1.1 -| 0.33 R1.2 -| 0.33 R1.3 -| 0.33 R1.4 -| 0.33 R1.5 -| 0.33 R2.1 -| 0.33 R2.2 -| 0.33 R2.3 -| 0.33 R2.4 -| 0.33 R2.5 -| 22 R35 -| 22 R36 -| 68 R40.1 -| 68 R40.2 -| 510 R10 -| 1.5k R9 -| 1.8k R4.1 -| 1.8k R4.2 -| 1.8k R4.3 -| 1.8k R4.4 -| 1.8k R4.5 -| 4.7k R11 -| 4.7k R19 -| 10k R13 -| 10k R14 -| 10k R15 -| 10k R16 -| 10k R17 -| 10k R22 -| 10k R23 -| 10k R24 -| 10k R26 -| 10k R37 -| 10k R38 -| 10k R39 -| 15k R8 -| 15k R20 -| 15k R21 -| 22k R3.1 -| 22k R3.2 -| 22k R3.3 -| 22k R3.4 -| 22k R3.5 -| 22k R7 -| 51k R5.1 -| 51k R5.2 -| 51k R5.3 -| 51k R5.4 -| 51k R5.5 -| 51k R6.1 -| 51k R6.2 -| 51k R6.3 -| 51k R6.4 -| 51k R6.5 -| 100k R18 -| 1M R12 -| 300 (II) R25 -| RT0805BRB071KL R27 -| RT0805BRB071KL R28 -| RT0805BRB071KL R29 -| RT0805BRB071KL R30 -| RT0805BRB071KL R31 -| RT0805BRB071KL R32 -| RT0805BRB071KL R33 -| RT0805BRB071KL R34 -| RESET SB1 -| BOOT SB2 -| B120-E3 VD1 -| B120-E3 VD3 -| PWR VD2 -| DTA114Y VT1 -| NTE2984 VT2.1 -| NTE2984 VT2.2 -| DB9 XP6 -| GPRM1-61 XP1 -| CONN_4 XP4 -| CONN_7 XP3 -| CONN_7 XP5 -| TRD XP2 -| Power XP7 -| DB9 XS1 +| 27p C10 +| 27p C11 +| 1n C2.1 +| 1n C2.2 +| 1n C2.3 +| 1n C2.4 +| 1n C2.5 +| 1n C3.1 +| 1n C3.2 +| 1n C3.3 +| 1n C3.4 +| 1n C3.5 +| 68n C1.1 +| 68n C1.2 +| 68n C1.3 +| 68n C1.4 +| 68n C1.5 +| 100n C7 +| 100n C8 +| 100n C9 +| 100n C12 +| 100n C14 +| 100n C15 +| 100n C16 +| 100n C17 +| 100n C18 +| 10u C5 +| 10u C13 +| 100u C6 +| 2200u, 40V C4 +| USB-MICRO-B CON1 +| RO-1224 DA5 +| LM1117MPX-3.3 DA6 +| USBLC6-2 DA4 +| IPS5451 DA1 +| TLE5205 DA2 +| ADM233L DD1 +| L6208N DD2.1 +| L6208N DD2.2 +| L6208N DD2.3 +| L6208N DD2.4 +| L6208N DD2.5 +| STM32F103 DD3 +| 8MHz G1 +| BMB2A0300AN1 L1 +| 0.33 R1.1 +| 0.33 R1.2 +| 0.33 R1.3 +| 0.33 R1.4 +| 0.33 R1.5 +| 0.33 R2.1 +| 0.33 R2.2 +| 0.33 R2.3 +| 0.33 R2.4 +| 0.33 R2.5 +| 22 R35 +| 22 R36 +| 68 R40.1 +| 68 R40.2 +| 510 R10 +| 1.5k R9 +| 1.8k R4.1 +| 1.8k R4.2 +| 1.8k R4.3 +| 1.8k R4.4 +| 1.8k R4.5 +| 4.7k R11 +| 4.7k R19 +| 10k R13 +| 10k R14 +| 10k R15 +| 10k R16 +| 10k R17 +| 10k R22 +| 10k R23 +| 10k R24 +| 10k R26 +| 10k R37 +| 10k R38 +| 10k R39 +| 15k R8 +| 15k R20 +| 15k R21 +| 22k R3.1 +| 22k R3.2 +| 22k R3.3 +| 22k R3.4 +| 22k R3.5 +| 22k R7 +| 51k R5.1 +| 51k R5.2 +| 51k R5.3 +| 51k R5.4 +| 51k R5.5 +| 51k R6.1 +| 51k R6.2 +| 51k R6.3 +| 51k R6.4 +| 51k R6.5 +| 100k R18 +| 1M R12 +| 300 (II) R25 +| RT0805BRB071KL R27 +| RT0805BRB071KL R28 +| RT0805BRB071KL R29 +| RT0805BRB071KL R30 +| RT0805BRB071KL R31 +| RT0805BRB071KL R32 +| RT0805BRB071KL R33 +| RT0805BRB071KL R34 +| RESET SB1 +| BOOT SB2 +| B120-E3 VD1 +| B120-E3 VD3 +| PWR VD2 +| DTA114Y VT1 +| NTE2984 VT2.1 +| NTE2984 VT2.2 +| DB9 XP6 +| GPRM1-61 XP1 +| CONN_4 XP4 +| CONN_7 XP3 +| CONN_7 XP5 +| TRD XP2 +| Power XP7 +| DB9 XS1 #End Cmp #End List diff --git a/schematic/ALL.sch b/schematic/ALL.sch index d228bc4..6105871 100644 --- a/schematic/ALL.sch +++ b/schematic/ALL.sch @@ -1,4 +1,4 @@ -EESchema Schematic File Version 2 date Пн 29 сен 2014 14:40:29 +EESchema Schematic File Version 2 date Вт 07 окт 2014 17:18:47 LIBS:power LIBS:device LIBS:transistors @@ -41,7 +41,7 @@ $Descr A3 16535 11693 encoding utf-8 Sheet 1 12 Title "IR-spectrometer Control System" -Date "29 sep 2014" +Date "7 oct 2014" Rev "" Comp "SAO RAS" Comment1 "" diff --git a/schematic/MCU_module.sch b/schematic/MCU_module.sch index 4101367..b6613ed 100644 --- a/schematic/MCU_module.sch +++ b/schematic/MCU_module.sch @@ -1,4 +1,4 @@ -EESchema Schematic File Version 2 date Пн 29 сен 2014 14:40:29 +EESchema Schematic File Version 2 date Вт 07 окт 2014 17:18:47 LIBS:power LIBS:device LIBS:transistors @@ -41,7 +41,7 @@ $Descr A3 16535 11693 encoding utf-8 Sheet 3 12 Title "MCU module on STM32F103" -Date "29 sep 2014" +Date "7 oct 2014" Rev "" Comp "SAO RAS" Comment1 "" diff --git a/schematic/ST3232.sch b/schematic/ST3232.sch index a475ee0..e30654d 100644 --- a/schematic/ST3232.sch +++ b/schematic/ST3232.sch @@ -1,4 +1,4 @@ -EESchema Schematic File Version 2 date Пн 29 сен 2014 14:40:29 +EESchema Schematic File Version 2 date Вт 07 окт 2014 17:18:47 LIBS:power LIBS:device LIBS:transistors @@ -41,7 +41,7 @@ $Descr A4 11693 8268 encoding utf-8 Sheet 5 12 Title "RS-232 level converter" -Date "29 sep 2014" +Date "7 oct 2014" Rev "" Comp "SAO RAS" Comment1 "" diff --git a/schematic/STM32_PINS b/schematic/STM32_PINS index 3bef65f..b3203c5 100644 --- a/schematic/STM32_PINS +++ b/schematic/STM32_PINS @@ -1,103 +1,103 @@ - +Functional map of MCU pins -# -001 PE2 DIR_3 direction of steppers' rotation +# name functionality +001 PE2 DIR_3 direction of steppers' rotation 002 PE3 DIR_4 003 PE4 DIR_5 -004 -005 -006 -007 -008 -009 -010 VSS -011 VDD -012 OSC_IN -013 OSC_OUT -014 NRST RST -015 PC0 \ -016 PC1 | ADG506 address -017 PC2 | selection -018 PC3 / -019 VSSA 0v analog +004 PE6 DG_FEEDBACK feedback from power switch POW_LOAD (+10..12V) +005 - +006 - +007 - +008 - +009 - +010 VSS GND +011 VDD +3.3V +012 OSC_IN 8MHz in +013 OSC_OUT 8MHz out +014 NRST Reset +015 PC0 SHTR Shutter on pulse +016 PC1 SHTR_FB Error signal from shutter H-bridge +017 PC2 POW0 Shutter polarity (open/close) +018 - +019 VSSA 0v analog 020 VREF- ref (0v) 021 VREF+ ref (+3.3v) 022 VDDA +3.3V analog -023 -024 PA1 TIM2 timer for motors 4&5 -025 PA2 UART_TX RS-232 -026 PA3 UART_RX -027 VSS -028 VDD -029 PA4 7\ -030 PA5 6 | -031 PA6 5 | -032 PA7 4 | ADC 12bit input channels (TRD) -033 PC4 3 | -034 PC5 2 | -035 PB0 1 | -036 PB1 0/ +023 - +024 - +025 PA2 1WIRE_TX 1-wire interface +026 PA3 1WIRE_RX +027 VSS GND +028 VDD +3.3V +029 PA4 ADC7\ +030 PA5 ADC6 | +031 PA6 ADC5 | +032 PA7 ADC4 | ADC 12bit input channels (TRD) +033 PC4 ADC3 | +034 PC5 ADC2 | +035 PB0 ADC1 | +036 PB1 ADC0/ 037 BOOT1 BOOT 100k resistor to GND -038 PE7 EN1 \ +038 PE7 EN1 \ 039 PE8 EN2 | -040 PE9 EN3 | enable Xth stepper motor +040 PE9 EN3 | enable Xth stepper motor 041 PE10 EN4 | 042 PE11 EN5 / -043 PE12 POW0\ -044 PE13 POW1 | Power load (12V, up to 17A on single channel) -045 PE14 POW2 | -046 PE15 POW3/ -047 PB10 USART3_TX 1-wire data tx/rx +043 PE12 POW2\ +044 PE13 POW1/ Power load (10..12V, pull-down) +045 - +046 - +047 PB10 USART3_TX RS-232 (master) 048 PB11 USART3_RX -049 VSS -050 VDD -051 +049 VSS GND +050 VDD +3.3V +051 - 052 SPI2_SCK \ -053 SPI2_MISO | External SPI connection +053 SPI2_MISO | External SPI connection (at edge of the board) 054 SPI2_MOSI / -055 PD8 \ Tur3[1..2] Upper filters turret Hall 1 & 2 -056 PD9 / -057 PD10 \ LS1 Linear stage 1 (long) DOWN end-switch -058 PD11 / Linear stage 1 (long) UP end-switch -059 PD12 \ LS2 Linear stage 2 (short) DOWN end-switch -060 PD13 / Linear stage 2 (short) UP end-switch -061 -062 -063 PC6 TIM1 timer for stepper motors 1..3 -064 PC7 \ -065 PC8 | -066 PC9 | EXT External ports + -067 PA8 | -068 PA9 | TX External UART (+ boot UART) -069 PA10 / RX -070 PA11 USB_DM USB data- -071 PA12 USB_DP USB data+ -072 -073 -074 VSS -075 VDD -076 -077 -078 -079 PC11 USB_DISC disconnect USB) -080 -081 PD0 \ -082 PD1 | Tur1 Slits turret Hall sensors +055 - +056 - +057 PD10 EXT0\ +058 PD11 EXT1 | ADG506 address selection +059 PD12 EXT2 | or custom external ports +060 PD13 EXT3/ +061 - +062 PD15 TIM2 timer for motors 4&5 +063 PC6 TIM1 timer for stepper motors 1..3 +064 PC7 \ LS1 Linear stage 1 (long) DOWN end-switch +065 PC8 / Linear stage 1 (long) UP end-switch +066 PC9 \ LS2 Linear stage 2 (short) DOWN end-switch +067 PA8 / Linear stage 2 (short) UP end-switch +068 PA9 BOOT_TX \ UART1 (slave): boot + ext UART +069 PA10 BOOT_RX / +070 PA11 USB_DM USB data- +071 PA12 USB_DP USB data+ +072 - +073 - +074 VSS GND +075 VDD +3.3V +076 - +077 - +078 PC10 USB_POWER +3V when USB connected +079 PC11 USB_DISC software USB disconnection (low lewel for bipolar VT1, high level for p-channel MOSFET) +080 - +081 PD0 \ +082 PD1 | Tur1 Slits turret Hall sensors 083 PD2 | 084 PD3 / 085 PD4 \ -086 PD5 | Tur2 Middle filters turret Hall sensors -087 PD6 / Upper filters turret Hall 0 -088 PD7 Tur3_0 -089 SPI1_SCK -090 SPI1_MISO -091 SPI1_MOSI/I2C_SMBAI -092 -093 -094 BOOT BOOT Button to boot from bootloader -095 I2C_SCL/CANRX -096 I2C_SDA/CANTX -097 PE0 DIR_1 direction of SM 1,2 +086 PD5 | Tur2 Middle filters turret Hall sensors +087 PD6 / +088 PD7 Tur3_0 Upper filters turret Hall 0 +089 SPI1_SCK \ +090 SPI1_MISO | SPI connection (near USB connector) +091 SPI1_MOSI/I2C_SMBAI/ +092 PB6 Tur3_1 \ Upper filters turret Hall 1,2 +093 PB7 Tur3_2 / +094 BOOT BOOT Button to boot from bootloader +095 I2C_SCL/CANRX \ External CAN connection (or I2S, etc) +096 I2C_SDA/CANTX / +097 PE0 DIR_1 direction of SM 1,2 098 PE1 DIR_2 -099 VSS -100 VDD +099 VSS +100 VDD diff --git a/schematic/Shutter_MOSFET.sch b/schematic/Shutter_MOSFET.sch index d67fd0a..99fb304 100644 --- a/schematic/Shutter_MOSFET.sch +++ b/schematic/Shutter_MOSFET.sch @@ -1,4 +1,4 @@ -EESchema Schematic File Version 2 date Пн 29 сен 2014 14:40:29 +EESchema Schematic File Version 2 date Вт 07 окт 2014 17:18:47 LIBS:power LIBS:device LIBS:transistors @@ -41,7 +41,7 @@ $Descr A4 11693 8268 encoding utf-8 Sheet 12 12 Title "Power load module" -Date "29 sep 2014" +Date "7 oct 2014" Rev "" Comp "SAO RAS" Comment1 "" diff --git a/schematic/USB_inp.sch b/schematic/USB_inp.sch index edff866..a05675f 100644 --- a/schematic/USB_inp.sch +++ b/schematic/USB_inp.sch @@ -1,4 +1,4 @@ -EESchema Schematic File Version 2 date Пн 29 сен 2014 14:40:29 +EESchema Schematic File Version 2 date Вт 07 окт 2014 17:18:47 LIBS:power LIBS:device LIBS:transistors @@ -41,7 +41,7 @@ $Descr A4 11693 8268 encoding utf-8 Sheet 4 12 Title "USB input circuit" -Date "29 sep 2014" +Date "7 oct 2014" Rev "" Comp "SAO RAS" Comment1 "" @@ -301,10 +301,20 @@ Wire Wire Line Wire Wire Line 3900 2500 2500 2500 Connection ~ 2500 2500 -Connection ~ 3900 2500 -Wire Wire Line - 5200 2000 3900 2000 -Wire Wire Line - 3900 2000 3900 3300 Connection ~ 3900 3100 +Wire Wire Line + 3900 3300 3900 2500 +$Comp +L +3.3V #PWR? +U 1 1 5433F723 +P 5200 1900 +F 0 "#PWR?" H 5200 1860 30 0001 C CNN +F 1 "+3.3V" H 5200 2010 30 0000 C CNN +F 2 "" H 5200 1900 60 0000 C CNN +F 3 "" H 5200 1900 60 0000 C CNN + 1 5200 1900 + 1 0 0 -1 +$EndComp +Wire Wire Line + 5200 1900 5200 2000 $EndSCHEMATC diff --git a/schematic/motors.sch b/schematic/motors.sch index 67b1be8..aab09d3 100644 --- a/schematic/motors.sch +++ b/schematic/motors.sch @@ -1,4 +1,4 @@ -EESchema Schematic File Version 2 date Пн 29 сен 2014 14:40:29 +EESchema Schematic File Version 2 date Вт 07 окт 2014 17:18:47 LIBS:power LIBS:device LIBS:transistors @@ -41,7 +41,7 @@ $Descr A4 11693 8268 encoding utf-8 Sheet 2 12 Title "Stepper motor module" -Date "29 sep 2014" +Date "7 oct 2014" Rev "" Comp "SAO RAS" Comment1 "" diff --git a/schematic/power_MOSFET.sch b/schematic/power_MOSFET.sch index bc087b9..3049741 100644 --- a/schematic/power_MOSFET.sch +++ b/schematic/power_MOSFET.sch @@ -1,4 +1,4 @@ -EESchema Schematic File Version 2 date Пн 29 сен 2014 14:40:29 +EESchema Schematic File Version 2 date Вт 07 окт 2014 17:18:47 LIBS:power LIBS:device LIBS:transistors @@ -41,7 +41,7 @@ $Descr A4 11693 8268 encoding utf-8 Sheet 11 12 Title "Power load module" -Date "29 sep 2014" +Date "7 oct 2014" Rev "" Comp "SAO RAS" Comment1 "" diff --git a/with_opencm3/Makefile b/with_opencm3/Makefile index 52afae3..8e487d8 100644 --- a/with_opencm3/Makefile +++ b/with_opencm3/Makefile @@ -1,9 +1,11 @@ BINARY = ircontroller BOOTPORT ?= /dev/ttyUSB0 BOOTSPEED ?= 115200 -LDSCRIPT = stm32-h103.ld +# change this linking script depending on particular MCU model, +# for example, if you have STM32F103VBT6, you should write: +LDSCRIPT = ld/stm32f103xB.ld LIBNAME = opencm3_stm32f1 -DEFS = -DSTM32F1 +DEFS = -DSTM32F1 -DEBUG OBJDIR = mk INDEPENDENT_HEADERS= @@ -11,7 +13,6 @@ INDEPENDENT_HEADERS= FP_FLAGS ?= -msoft-float ARCH_FLAGS = -mthumb -mcpu=cortex-m3 $(FP_FLAGS) -mfix-cortex-m3-ldrd - ############################################################################### # Executables PREFIX ?= arm-none-eabi @@ -46,7 +47,7 @@ SCRIPT_DIR = $(OPENCM3_DIR)/scripts ############################################################################### # C flags CFLAGS += -Os -g -CFLAGS += -Wextra -Wshadow -Wimplicit-function-declaration +CFLAGS += -Wall -Wextra -Wshadow -Wimplicit-function-declaration CFLAGS += -Wredundant-decls # -Wmissing-prototypes -Wstrict-prototypes CFLAGS += -fno-common -ffunction-sections -fdata-sections diff --git a/with_opencm3/NVIC b/with_opencm3/NVIC new file mode 100644 index 0000000..9c78d63 --- /dev/null +++ b/with_opencm3/NVIC @@ -0,0 +1 @@ +don't forget to call nvic_enable_irq(irq) to allow interrupts diff --git a/with_opencm3/README b/with_opencm3/README index ba85e46..d7d934b 100644 --- a/with_opencm3/README +++ b/with_opencm3/README @@ -1,3 +1,11 @@ +The work begins +First PCB have been prodused, so I need "only" to solder elements & finish the code + +Pinout of MCI is in file schematics/STM32_PINS + + +-- OLD -- + This is a sketch for futher work I found that libopencm3 is more friendly than SPL. Also I have some new thoughts about modular system: for flexibility. diff --git a/with_opencm3/cdcacm.c b/with_opencm3/cdcacm.c index 0130597..f19fc07 100644 --- a/with_opencm3/cdcacm.c +++ b/with_opencm3/cdcacm.c @@ -292,20 +292,19 @@ usbd_device *USB_init(){ return current_usb; } -uint8_t send_block = 0; +mutex_t send_block_mutex = MUTEX_UNLOCKED; /** * Put byte into USB buffer to send * @param byte - a byte to put into a buffer */ void usb_send(uint8_t byte){ - while(send_block); // wait for unlock - send_block = 1; + mutex_lock(&send_block_mutex); USB_Tx_Buffer[USB_Tx_ptr++] = byte; if(USB_Tx_ptr == USB_TX_DATA_SIZE){ // buffer can be overflowed - send it! - send_block = 0; + mutex_unlock(&send_block_mutex); usb_send_buffer(); - } - send_block = 0; + }else + mutex_unlock(&send_block_mutex); } /** @@ -313,8 +312,7 @@ void usb_send(uint8_t byte){ * this function runs when buffer is full or on SysTick */ void usb_send_buffer(){ - if(send_block) return; - send_block = 1; + if(MUTEX_LOCKED == mutex_trylock(&send_block_mutex)) return; if(USB_Tx_ptr){ if(current_usb && USB_connected){ // usbd_ep_write_packet return 0 if previous packet isn't transmit yet @@ -323,5 +321,5 @@ void usb_send_buffer(){ } USB_Tx_ptr = 0; } - send_block = 0; + mutex_unlock(&send_block_mutex); } diff --git a/with_opencm3/client-term/get_T.m b/with_opencm3/client-term/get_T.m index 1e980e3..f8c5e12 100644 --- a/with_opencm3/client-term/get_T.m +++ b/with_opencm3/client-term/get_T.m @@ -31,14 +31,17 @@ function [Time T Tfxd] = get_T(filename, filter_treshold) endfor endif - plot(Time, R); + Leg = ['1'; '2'; '3'; '4'; '5'; '6'; '7'; '8']; + + more_colors(plot(Time, R), 8); Tit = sprintf("Resistance, \\Omega"); xlabel("Time, s"); ylabel("R, \\Omega"); title(Tit); print -dpng -color resistance.png; close - plot(Time, T); + more_colors(plot(Time, T), 8); Tit = sprintf("Temperature, ^\\circ{}C"); xlabel("Time, s"); ylabel("T, ^\\circ{}C"); title(Tit); + legend(Leg); print -dpng -color temperatures.png; close @@ -46,12 +49,18 @@ function [Time T Tfxd] = get_T(filename, filter_treshold) Tavr = mean(T, 2); Tadd = mean(T - repmat(Tavr, [1 8])); Tfxd = T - repmat(Tadd,[size(T,1) 1]); - plot(Time, Tfxd); + more_colors(plot(Time, Tfxd), 8); Tit = sprintf("Temperature fixed to average value, ^\\circ{}C"); xlabel("Time, s"); ylabel("T, ^\\circ{}C"); title(Tit); print -dpng -color temperatures_fixed.png; + legend(Leg); close printf("differences:\n"); printf("%g\n", -Tadd); endfunction - +function more_colors(h, N) + palette = jet (N); + for i = 1:N + set(h(i),"color",palette(i,:)) + endfor +endfunction diff --git a/with_opencm3/hardware_ini.c b/with_opencm3/hardware_ini.c index f667e08..ec4b112 100644 --- a/with_opencm3/hardware_ini.c +++ b/with_opencm3/hardware_ini.c @@ -19,24 +19,108 @@ * MA 02110-1301, USA. */ +/* + * All hardware-dependent initialisation & definition should be placed here + * and in hardware_ini.h + * + */ + #include "main.h" #include "hardware_ini.h" volatile uint16_t ADC_value[8]; // ADC DMA value -/** - * GPIO initialisaion: clocking + ports setup +/* + * Configure SPI ports */ -void GPIO_init(){ - rcc_periph_clock_enable(RCC_GPIOC); - gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_2_MHZ, - GPIO_CNF_OUTPUT_PUSHPULL, GPIO11|GPIO12); // LED + USB - // AD7794 addr + en - gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_2_MHZ, - GPIO_CNF_OUTPUT_PUSHPULL, ADC_ADDR_MASK | GPIO10); // ADDRESS: PC6..9; EN: PC10 - GPIO_BSRR(GPIOC) = (ADC_ADDR_MASK | GPIO10) << 16; // clear address & disable com +/* + * SPI1 remapped: + * SCK - PB3 + * MISO - PB4 + * MOSI - PB5 + */ +void SPI1_init(){ + // enable AFIO & other clocking + rcc_peripheral_enable_clock(&RCC_APB2ENR, + RCC_APB2ENR_SPI1EN | RCC_APB2ENR_AFIOEN | RCC_APB2ENR_IOPBEN); + // remap SPI1 (change pins from PA5..7 to PB3..5); also turn off JTAG + gpio_primary_remap(AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_OFF, AFIO_MAPR_SPI1_REMAP); + // SCK, MOSI - push-pull output + gpio_set_mode(GPIO_BANK_SPI1_RE_SCK, GPIO_MODE_OUTPUT_50_MHZ, + GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_SPI1_RE_SCK); + gpio_set_mode(GPIO_BANK_SPI1_RE_MOSI, GPIO_MODE_OUTPUT_50_MHZ, + GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_SPI1_RE_MOSI); + // MISO - opendrain in + gpio_set_mode(GPIO_BANK_SPI1_RE_MISO, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO_SPI1_RE_MISO); + spi_reset(SPI1); + /* Set up SPI in Master mode with: + * Clock baud rate: 1/128 of peripheral clock frequency (APB2, 72MHz) + * Clock polarity: Idle High + * Clock phase: Data valid on 2nd clock pulse + * Data frame format: 8-bit + * Frame format: MSB First + */ + spi_init_master(SPI1, SPI_CR1_BAUDRATE_FPCLK_DIV_128, SPI_CR1_CPOL_CLK_TO_1_WHEN_IDLE, + SPI_CR1_CPHA_CLK_TRANSITION_2, SPI_CR1_DFF_8BIT, SPI_CR1_MSBFIRST); + nvic_enable_irq(NVIC_SPI1_IRQ); // enable SPI interrupt } +/* + * SPI2: + * SCK - PB13 + * MISO - PB14 + * MOSI - PB15 + */ +void SPI2_init(){ + // turn on clocking + //rcc_periph_clock_enable(RCC_SPI2 | RCC_GPIOB); + rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_SPI2EN); + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_AFIOEN | RCC_APB2ENR_IOPBEN); + // SCK, MOSI - push-pull output + gpio_set_mode(GPIO_BANK_SPI2_SCK, GPIO_MODE_OUTPUT_50_MHZ, + GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_SPI2_SCK); + gpio_set_mode(GPIO_BANK_SPI2_MOSI, GPIO_MODE_OUTPUT_50_MHZ, + GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_SPI2_MOSI); + // MISO - opendrain in + gpio_set_mode(GPIO_BANK_SPI2_MISO, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO_SPI2_MISO); + spi_reset(SPI2); + /* Set up SPI in Master mode with: + * Clock baud rate: 1/64 of peripheral clock frequency (APB1, 36MHz) + * Clock polarity: Idle High + * Clock phase: Data valid on 2nd clock pulse + * Data frame format: 8-bit + * Frame format: MSB First + */ + spi_init_master(SPI2, SPI_CR1_BAUDRATE_FPCLK_DIV_64, SPI_CR1_CPOL_CLK_TO_1_WHEN_IDLE, + SPI_CR1_CPHA_CLK_TRANSITION_2, SPI_CR1_DFF_8BIT, SPI_CR1_MSBFIRST); + nvic_enable_irq(NVIC_SPI2_IRQ); // enable SPI interrupt +} + +/** + * GPIO initialisaion: clocking + pins setup + */ +void GPIO_init(){ +/* rcc_periph_clock_enable(RCC_AFIO); + rcc_periph_clock_enable(RCC_SPI1); + rcc_periph_clock_enable(RCC_GPIOC);*/ + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN | + RCC_APB2ENR_IOPBEN | RCC_APB2ENR_IOPCEN | RCC_APB2ENR_IOPDEN | + RCC_APB2ENR_IOPEEN); + // USB_DISC: push-pull + gpio_set_mode(USB_DISC_PORT, GPIO_MODE_OUTPUT_2_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, USB_DISC_PIN); + // USB_POWER: open drain, externall pull down with R7 (22k) + gpio_set_mode(USB_POWER_PORT, GPIO_MODE_INPUT, + GPIO_CNF_INPUT_FLOAT, USB_POWER_PIN); + // AD7794 addr + en + gpio_set_mode(ADC_ADDR_PORT, GPIO_MODE_OUTPUT_2_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, ADC_ADDR_MASK | ADC_EN_PIN); // ADDRESS: PD10..12; EN: PD13 + gpio_clear(ADC_ADDR_PORT, ADC_ADDR_MASK | ADC_EN_PIN); // clear address & turn switch off +} + +/* + * SysTick used for system timer with period of 1ms + */ void SysTick_init(){ systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); // Systyck: 72/8=9MHz systick_set_reload(8999); // 9000 pulses: 1kHz @@ -44,13 +128,31 @@ void SysTick_init(){ systick_counter_enable(); } +/* + * Due to inconvenient pins position on STM32F103VxT6 I had to make this strange location: + * my channel # -> ADC1/2 channel # + * 0 -> 9 PB1 + * 1 -> 8 PB0 + * 2 -> 15 PC5 + * 3 -> 14 PC4 + * 4 -> 7 PA7 + * 5 -> 6 PA6 + * 6 -> 5 PA5 + * 7 -> 4 PA4 + */ +uint8_t adc_channel_array[16] = {9,8,15,14,7,6,5,4}; +#define ADC_CHANNELS_NUMBER 8 void ADC_init(){ rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_ADC1EN); // enable clocking rcc_periph_clock_enable(RCC_ADC1); rcc_set_adcpre(RCC_CFGR_ADCPRE_PCLK2_DIV4); - rcc_periph_clock_enable(RCC_GPIOB | RCC_GPIOC); // clocking for ADC ports - gpio_set_mode(GPIOB, GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, 3); // ADC8 - PB0, ADC9 -PB1 - gpio_set_mode(GPIOC, GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, 63); // ADC10-15: PC0-PC5 + rcc_periph_clock_enable(RCC_GPIOA | RCC_GPIOB | RCC_GPIOC); // clocking for ADC ports + // channels 4-7: PA7-PA4 + gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, GPIO4|GPIO5|GPIO6|GPIO7); + // channels 0,1: PB1, PB0 + gpio_set_mode(GPIOB, GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, GPIO0|GPIO1); + // channels 2,3: PC5, PC4 + gpio_set_mode(GPIOC, GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, GPIO4|GPIO5); // Make sure the ADC doesn't run during config adc_off(ADC1); @@ -60,7 +162,7 @@ void ADC_init(){ dma_channel_reset(DMA1, DMA_CHANNEL1); //DMA_DeInit(DMA1_Channel1); dma_set_peripheral_address(DMA1, DMA_CHANNEL1, (uint32_t) &(ADC_DR(ADC1))); // DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address; dma_set_memory_address(DMA1, DMA_CHANNEL1, (uint32_t) ADC_value); // DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADC_value; - dma_set_number_of_data(DMA1, DMA_CHANNEL1, 8); // DMA_InitStructure.DMA_BufferSize = 1; + dma_set_number_of_data(DMA1, DMA_CHANNEL1, ADC_CHANNELS_NUMBER); // DMA_InitStructure.DMA_BufferSize = 1; dma_set_read_from_peripheral(DMA1, DMA_CHANNEL1); // DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL1); // DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable; dma_disable_peripheral_increment_mode(DMA1, DMA_CHANNEL1); // DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; @@ -76,8 +178,8 @@ void ADC_init(){ adc_set_continuous_conversion_mode(ADC1); // ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; adc_disable_external_trigger_regular(ADC1); // ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; adc_set_right_aligned(ADC1); // ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; - //adc_set_sample_time_on_all_channels(ADC1, ADC_SMPR_SMP_239DOT5CYC); // ADC_SampleTime_239Cycles5 - adc_set_sample_time(ADC1, ADC_CHANNEL8, ADC_SMPR_SMP_239DOT5CYC); // ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 1, ADC_SampleTime_239Cycles5); + adc_set_sample_time_on_all_channels(ADC1, ADC_SMPR_SMP_239DOT5CYC); // ADC_SampleTime_239Cycles5 + //adc_set_sample_time(ADC1, ADC_CHANNEL8, ADC_SMPR_SMP_239DOT5CYC); // ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 1, ADC_SampleTime_239Cycles5); adc_enable_dma(ADC1); // ADC_DMACmd(ADC1, ENABLE); adc_power_on(ADC1); // ADC_Cmd(ADC1, ENABLE); } @@ -87,13 +189,112 @@ void ADC_init(){ * First call ADC_init(), than wait a little and call this function */ void ADC_calibrate_and_start(){ - uint8_t channel_array[16] = {8,9,10,11,12,13,14,15}; - // adc_set_regular_sequence 1 channel -- 0 // ADC_InitStructure.ADC_NbrOfChannel = 1; - channel_array[0] = ADC_CHANNEL8; - adc_set_regular_sequence(ADC1, 8, channel_array); + adc_set_regular_sequence(ADC1, ADC_CHANNELS_NUMBER, adc_channel_array); adc_reset_calibration(ADC1); adc_calibration(ADC1); adc_start_conversion_regular(ADC1); // ADC_SoftwareStartConvCmd(ADC1, ENABLE); adc_start_conversion_direct(ADC1); } +uint16_t tim2_buff[8] = {10,20,30,40,50,60,70,80}; +uint16_t tim2_inbuff[8]; + +void init_dmatimer(){ // tim2_ch4 - PA3, no remap + gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ, + GPIO_CNF_OUTPUT_ALTFN_OPENDRAIN, GPIO3); + rcc_periph_clock_enable(RCC_TIM2); + timer_reset(TIM2); + // timers have frequency of 1MHz -- 1us for one step + // 36MHz of APB1 + timer_set_mode(TIM2, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP); + // 72MHz div 72 = 1MHz + timer_set_prescaler(TIM2, 71); // prescaler is (div - 1) + timer_continuous_mode(TIM2); // automatically reload + timer_enable_preload(TIM2); // force changing period + timer_set_period(TIM2, 86); // period is 87us + timer_enable_update_event(TIM2); + timer_set_oc_mode(TIM2, TIM_OC4, TIM_OCM_PWM1); // edge-aligned mode + timer_enable_oc_preload(TIM2, TIM_OC4); + timer_enable_oc_output(TIM2, TIM_OC4); + timer_enable_irq(TIM2, TIM_DIER_UDE | TIM_DIER_CC4DE | TIM_DIER_CC3DE); + timer_set_oc_polarity_low(TIM2, TIM_OC4); + + // TIM2_CH4 - DMA1, channel 7 + rcc_periph_clock_enable(RCC_DMA1); + dma_channel_reset(DMA1, DMA_CHANNEL7); + dma_set_peripheral_address(DMA1, DMA_CHANNEL7, (uint32_t) &(TIM_CCR4(TIM2))); + dma_set_read_from_memory(DMA1, DMA_CHANNEL7); + dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL7); + dma_disable_peripheral_increment_mode(DMA1, DMA_CHANNEL7); + dma_set_peripheral_size(DMA1, DMA_CHANNEL7, DMA_CCR_PSIZE_16BIT); + dma_set_memory_size(DMA1, DMA_CHANNEL7, DMA_CCR_MSIZE_16BIT); + dma_enable_transfer_error_interrupt(DMA1, DMA_CHANNEL7); + dma_enable_transfer_complete_interrupt(DMA1, DMA_CHANNEL7); + dma_set_memory_address(DMA1, DMA_CHANNEL7, (uint32_t)tim2_buff); + + nvic_enable_irq(NVIC_DMA1_CHANNEL7_IRQ); // enable dma1_channel7_isr + + // capture: TIM2_CH3 + timer_ic_set_input(TIM2, TIM_IC3, TIM_IC_IN_TI4); + timer_set_oc_polarity_high(TIM2, TIM_OC3); + timer_ic_enable(TIM2, TIM_IC3); + timer_enable_oc_output(TIM2, TIM_OC3); + + // configure DMA1 Channel1 (ADC1) + dma_channel_reset(DMA1, DMA_CHANNEL1); + dma_set_peripheral_address(DMA1, DMA_CHANNEL1, (uint32_t) &(TIM_CCR3(TIM2))); + dma_set_memory_address(DMA1, DMA_CHANNEL1, (uint32_t) tim2_inbuff); + dma_set_number_of_data(DMA1, DMA_CHANNEL1, 8); + dma_set_read_from_peripheral(DMA1, DMA_CHANNEL1); + dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL1); + dma_disable_peripheral_increment_mode(DMA1, DMA_CHANNEL1); + dma_set_peripheral_size(DMA1, DMA_CHANNEL1, DMA_CCR_PSIZE_16BIT); + dma_set_memory_size(DMA1, DMA_CHANNEL1, DMA_CCR_MSIZE_16BIT); + nvic_enable_irq(NVIC_DMA1_CHANNEL1_IRQ); + dma_enable_transfer_error_interrupt(DMA1, DMA_CHANNEL1); + dma_enable_transfer_complete_interrupt(DMA1, DMA_CHANNEL1); +} + +void run_dmatimer(){ + int i; + DMA1_IFCR = DMA_ISR_TEIF7|DMA_ISR_HTIF7|DMA_ISR_TCIF7|DMA_ISR_GIF7 | + DMA_ISR_TEIF1|DMA_ISR_HTIF1|DMA_ISR_TCIF1|DMA_ISR_GIF1; // clear flags + + dma_set_number_of_data(DMA1, DMA_CHANNEL7, 8); + timer_set_dma_on_compare_event(TIM2); + timer_enable_oc_output(TIM2, TIM_OC4); + dma_enable_channel(DMA1, DMA_CHANNEL7); + timer_enable_counter(TIM2); + + for(i = 0; i < 8; i++) tim2_inbuff[i] = 0; + dma_set_number_of_data(DMA1, DMA_CHANNEL1, 8); + dma_enable_channel(DMA1, DMA_CHANNEL1); +} + +void dma1_channel7_isr(){ + if(DMA1_ISR & DMA_ISR_TCIF7) { + DMA1_IFCR = DMA_IFCR_CTCIF7; + dma_disable_channel(DMA1, DMA_CHANNEL7); + }else if(DMA1_ISR & DMA_ISR_TEIF7){ + DMA1_IFCR = DMA_IFCR_CTEIF7; + MSG("out transfer error\n"); + } +} + +void dma1_channel1_isr(){ + int i; + if(DMA1_ISR & DMA_ISR_TCIF1) { + DMA1_IFCR = DMA_IFCR_CTCIF1; + dma_disable_channel(DMA1, DMA_CHANNEL1); + timer_disable_counter(TIM2); + gpio_set(GPIOA, GPIO3); + for(i = 0; i < 8; i++){ + print_int(tim2_inbuff[i], lastsendfun); + MSG(" "); + } + MSG("\n"); + }else if(DMA1_ISR & DMA_ISR_TEIF1){ + DMA1_IFCR = DMA_IFCR_CTEIF1; + MSG("in transfer error\n"); + } +} diff --git a/with_opencm3/hardware_ini.h b/with_opencm3/hardware_ini.h index 57c1381..18e5f18 100644 --- a/with_opencm3/hardware_ini.h +++ b/with_opencm3/hardware_ini.h @@ -23,23 +23,72 @@ #ifndef __HARDWARE_INI_H__ #define __HARDWARE_INI_H__ + + extern volatile uint16_t ADC_value[]; // ADC DMA value -#define ADC_ADDR_MASK (GPIO6|GPIO7|GPIO8|GPIO9) #define TRD_NO 8 // number of TRD devices +// bits used to address external SPI ADC - PD10..12 +#define ADC_ADDR_MASK (GPIO10|GPIO11|GPIO12) +#define ADC_SET_ADDR(X) ((X << 10) & ADC_ADDR_MASK) +#define ADC_EN_PIN GPIO13 +#define ADC_ADDR_PORT GPIOD +void SPI1_init(); +void SPI2_init(); void GPIO_init(); void SysTick_init(); void ADC_init(); void ADC_calibrate_and_start(); +/* + * USB interface + */ +// USB_DICS (disconnect) - PC11 +#define USB_DISC_PIN GPIO11 +#define USB_DISC_PORT GPIOC +// USB_POWER (high level when USB connected to PC) +#define USB_POWER_PIN GPIO10 +#define USB_POWER_PORT GPIOC +// change signal level on USB diconnect pin +#define usb_disc_high() gpio_set(USB_DISC_PORT, USB_DISC_PIN) +#define usb_disc_low() gpio_clear(USB_DISC_PORT, USB_DISC_PIN) +// in case of pnp bipolar transistor on 1.5k pull-up disconnect means low level +// in case of p-channel FET on 1.5k pull-up change on/off disconnect means high level +#define usb_disconnect() usb_disc_low() +#define usb_connect() usb_disc_high() + +/* + * Stepper motors + * motors' interface use timers 1 & 2, so even hardware-dependent functions are + * moved to stepper_motors.c + */ +// PE7..11 - EN +#define MOROT_EN_MASK (0x1f << 7) +#define MOTOR_EN_PORT (GPIOE) +// N == 1..5 +#define MOTOR_EN_PIN(N) (GPIO6 << (N)) +// PE0..PE5 - DIR +#define MOROT_DIR_MASK (0x1f) +#define MOTOR_DIR_PORT (GPIOE) +// N == 1..5 +#define MOTOR_DIR_PIN(N) (GPIO0 << (N - 1)) +// timers: TIM1 - PC6, TIM2 - PD15 +#define MOTOR_TIM1_PORT (GPIOC) +#define MOTOR_TIM1_PIN (GPIO6) +#define MOTOR_TIM2_PORT (GPIOD) +#define MOTOR_TIM2_PIN (GPIO15) + /* * One Wire interface */ -// In case of using USART2 for 1-wire port, make corresponding change +// In case of using other USART for 1-wire port, make corresponding change // and redefine pins in OW_Init -//#define OW_USART_X USART2 -#define OW_USART_X USART3 +#define OW_USART_X USART2 +#define OW_RX_PORT GPIO_BANK_USART2_RX +#define OW_RX_PIN GPIO_USART2_RX +void init_dmatimer(); +void run_dmatimer(); #endif // __HARDWARE_INI_H__ diff --git a/with_opencm3/ircontroller.bin b/with_opencm3/ircontroller.bin index fbf5d8e..1aee385 100755 Binary files a/with_opencm3/ircontroller.bin and b/with_opencm3/ircontroller.bin differ diff --git a/with_opencm3/main.c b/with_opencm3/main.c index 8b5d4b1..7acc3f2 100644 --- a/with_opencm3/main.c +++ b/with_opencm3/main.c @@ -24,6 +24,7 @@ #include "cdcacm.h" #include "uart.h" #include "spi.h" +#include "stepper_motors.h" volatile uint32_t Timer = 0, tOVRFL = 0; // global timer (milliseconds), overflow counter usbd_device *usbd_dev; @@ -55,10 +56,7 @@ void read_next_TRD(){ //P("Step 0: read_next_TRD, N=", uart1_send); //print_int(N, uart1_send); //newline(uart1_send); - GPIO_BSRR(GPIOC) = N << 6; // set address - GPIO_BSRR(GPIOC) = GPIO10; // enable com - N++; // and increment TRD counter - if(N == TRD_NO) N = 0; + gpio_set(ADC_ADDR_PORT, ADC_SET_ADDR(N) | ADC_EN_PIN); // set address & enable switch val0 = val1 = 0; step++; break; @@ -102,17 +100,29 @@ void read_next_TRD(){ break; default: // last step - turn off multiplexer step = 0; - GPIO_BSRR(GPIOC) = (ADC_ADDR_MASK | GPIO10) << 16; // disable com & clear address bytes + gpio_clear(ADC_ADDR_PORT, ADC_ADDR_MASK | ADC_EN_PIN); // disable com & clear address bytes + N++; // and increment TRD counter + if(N == TRD_NO) N = 0; } } +//uint8_t curSPI = 1; + void AD7794_init(){ uint8_t i; ad7794_on = 0; i = reset_AD7794(); if(i != ADC_NO_ERROR){ if(i == ADC_ERR_NO_DEVICE){ - MSG("ADC signal is absent! Check connection.\r\n"); + // print_int(curSPI, lastsendfun); + MSG(": ADC signal is absent! Check connection.\r\n"); + /* if(curSPI == 1){ + curSPI = 2; + switch_SPI(SPI2); + }else{ + curSPI = 1; + switch_SPI(SPI1); + }*/ } }else{ if(!setup_AD7794(INTREFIN | REF_DETECTION | UNIPOLAR_CODING, IEXC_DIRECT | IEXC_1MA) @@ -133,11 +143,12 @@ int main(){ //rcc_clock_setup_in_hsi_out_48mhz(); // RCC clocking: 8MHz oscillator -> 72MHz system rcc_clock_setup_in_hse_8mhz_out_72mhz(); - // GPIO GPIO_init(); - gpio_set(GPIOC, GPIO11); // turn off USB - gpio_clear(GPIOC, GPIO12); // turn on LED + + steppers_init(); + + usb_disconnect(); // turn off USB // init USART1 UART_init(USART1); @@ -146,21 +157,26 @@ int main(){ usbd_dev = USB_init(); // init ADC - ADC_init(); +// ADC_init(); // SysTick is a system timer with 1mc period SysTick_init(); - SPI1_init(); - OW_Init(); +// switch_SPI(SPI2); // init SPI2 +// SPI_init(); + + switch_SPI(SPI1); // init SPI1 + SPI_init(); + //OW_Init(); // wait a little and then turn on USB pullup for (i = 0; i < 0x800000; i++) __asm__("nop"); - gpio_clear(GPIOC, GPIO11); - ADC_calibrate_and_start(); + usb_connect(); // turn on USB + //ADC_calibrate_and_start(); +init_dmatimer(); while(1){ usbd_poll(usbd_dev); if(usbdatalen){ // there's something in USB buffer @@ -174,10 +190,13 @@ int main(){ read_next_TRD(); } } + process_stepper_motors(); // check flags of motors' timers if(Timer - Old_timer > 999){ // one-second cycle Old_timer += 1000; - gpio_toggle(GPIOC, GPIO12); // toggle LED - if(!ad7794_on) AD7794_init(); // try to init ADC if it doesn't work + //gpio_toggle(GPIOC, GPIO12); // toggle LED + //gpio_toggle(GPIO_BANK_SPI2_MOSI, GPIO_SPI2_MOSI); + //gpio_toggle(GPIO_BANK_SPI2_SCK, GPIO_SPI2_SCK); + // if(!ad7794_on) AD7794_init(); // try to init ADC if it doesn't work //print_int(Timer/1000, usb_send); }else if(Timer < Old_timer){ // Timer overflow Old_timer = 0; diff --git a/with_opencm3/main.h b/with_opencm3/main.h index 9f48d0e..00f2da0 100644 --- a/with_opencm3/main.h +++ b/with_opencm3/main.h @@ -37,9 +37,12 @@ #include #include +#include "sync.h" // mutexes #include "user_proto.h" #include "AD7794.h" #include "onewire.h" +#include "stepper_motors.h" +#include "sensors.h" #define _U_ __attribute__((__unused__)) #define U8(x) ((uint8_t) x) diff --git a/with_opencm3/onewire.c b/with_opencm3/onewire.c index da5ee4c..3f574ee 100644 --- a/with_opencm3/onewire.c +++ b/with_opencm3/onewire.c @@ -24,8 +24,10 @@ #define OW_RST 0xf0 -// In/Out buffer -uint8_t ow_buf[8]; +uint8_t dev_amount = 0; // amount of 1-wire devices +uint8_t ID_buf[64] = {0}; // 1-wire devices ID buffer (8 bytes for every device) +uint8_t NUM_buf[8] = {0}; // numerical identificators for each sensor + /** * this function sends bits of ow_byte (LSB first) to 1-wire line * @param ow_byte - byte to convert @@ -46,22 +48,29 @@ void OW_SendBits(uint8_t ow_byte, uint8_t Nbits){ } } -/* - * Inverce conversion - read data (not more than 8 b - */ -uint8_t OW_ReadByte(){ +void OW_ClearBuff(){ UART_buff *curbuff = get_uart_buffer(OW_USART_X); - uint8_t ow_byte = 0, i, L, *buf; - if(!curbuff || !(L = curbuff->end)) return 0; // no data? + curbuff->end = 0; +} + +/* + * Inverce conversion - read data (not more than 8 bits) + */ +uint8_t OW_ConvertByte(uint8_t *bits, uint8_t L){ + uint8_t ow_byte = 0, i, *st = bits; if(L > 8) L = 8; // forget all other data - buf = curbuff->buf; - for(i = 0; i < L; i++, buf++){ + for(i = 0; i < L; i++, st++){ ow_byte = ow_byte >> 1; // prepare for next bit filling - if(*buf == OW_1){ + if(*st == OW_1){ ow_byte |= 0x80; // MSB = 1 } } - return ow_byte >> (8 - L); // shift to the end: L could be != 8 ??? + ow_byte >>= (8 - L); +print_hex(bits, L, lastsendfun); +lastsendfun(' '); +print_hex(&ow_byte, 1, lastsendfun); +newline(lastsendfun); + return ow_byte; // shift to the end: L could be != 8 ??? } @@ -88,7 +97,7 @@ void OW_Init(){ * * return 1 in case of 1-wire devices present; otherwise return 0 */ -uint8_t OW_Reset() { +uint8_t OW_Reset(){ uint8_t ow_presence; UART_buff *curbuff; // change speed to 9600 @@ -111,52 +120,61 @@ uint8_t OW_Reset() { return 0; } -/* +/** * Procedure of 1-wire communications * variables: - * sendReset - send RESET before transmission - * command - bytes sent to the bus (if we want to read, send OW_READ_SLOT) - * cLen - command buffer length (how many bytes to send) - * data - pointer for reading buffer (if reading needed) - * readStart - first byte to read (starts from 0) or OW_NO_READ (not read) - * - * return 1 if succeed, 0 if failure + * @param sendReset - send RESET before transmission + * @param command - bytes sent to the bus (if we want to read, send OW_READ_SLOT) + * @param cLen - command buffer length (how many bytes to send) + * @return 1 if succeed, 0 if failure */ -uint8_t OW_Send(uint8_t sendReset, uint8_t *command, uint8_t cLen, - uint8_t *data, uint8_t dLen, uint8_t readStart) { +uint8_t OW_Send(uint8_t sendReset, uint8_t *command, uint8_t cLen){ // if reset needed - send RESET and check bus if(sendReset){ if(OW_Reset() == 0){ return 0; } } - while(cLen > 0){ + while(cLen-- > 0){ OW_SendBits(*command, 8); command++; - cLen--; - // wait for EOT - while(!(USART_SR(OW_USART_X) & USART_SR_TC)); - // put data from bus into user buffer - if(readStart == 0 && dLen > 0){ - *data = OW_ReadByte(); - data++; - dLen--; + } + return 1; +} + +/** + * Check USART IN buffer for ready & fill user buffer with data on success + * @param buflen - expected buffer length + * @param data - pointer for reading buffer (if reading needed must be at least buflen-readStart bytes) + * @param readStart - first byte to read (starts from 0) or OW_NO_READ (not read) + * @return 0 if buffer not ready; 1 if OK + */ +uint8_t OW_Get(uint8_t buflen, uint8_t *data, uint8_t readStart){ + UART_buff *curbuff = get_uart_buffer(OW_USART_X); + uint8_t *buff = curbuff->buf; + if(curbuff->end < buflen/8) return 0; + while(buflen-- > 0){ + if(readStart == 0){ + *data++ = OW_ConvertByte(buff, 8); }else{ if(readStart != OW_NO_READ){ readStart--; } } + buff += 8; } + curbuff->end = 0; // zero counter return 1; } /* * scan 1-wire bus + * WARNING! The procedure works in real-time, so it is VERY LONG * num - max number of devices * buf - array for devices' ID's (8*num bytes) * return amount of founded devices - */ -uint8_t OW_Scan(uint8_t *buf, uint8_t num) { + * +uint8_t OW_Scan(uint8_t *buf, uint8_t num){ unsigned long path,next,pos; uint8_t bit,chk; uint8_t cnt_bit, cnt_byte, cnt_num; @@ -165,17 +183,19 @@ uint8_t OW_Scan(uint8_t *buf, uint8_t num) { do{ //(issue the 'ROM search' command) if( 0 == OW_WriteCmd(OW_SEARCH_ROM) ) return 0; - next=0; // next path to follow - pos=1; // path bit pointer + OW_Wait_TX(); + OW_ClearBuff(); // clear RX buffer + next = 0; // next path to follow + pos = 1; // path bit pointer for(cnt_byte = 0; cnt_byte != 8; cnt_byte++){ buf[cnt_num*8 + cnt_byte] = 0; for(cnt_bit = 0; cnt_bit != 8; cnt_bit++){ //(read two bits, 'bit' and 'chk', from the 1-wire bus) OW_SendBits(OW_R, 2); - bit = OW_ReadByte(); + OW_Wait_TX(); + bit = -----OW_ReadByte(); chk = bit & 0x02; // bit 1 bit = bit & 0x01; // bit 0 - //bit = (ow_buf[0] == OW_1); chk = (ow_buf[1] == OW_1); if(bit && chk) return 0; // error if(!bit && !chk){ // collision, both are zero if (pos & path) bit = 1; // if we've been here before @@ -186,11 +206,54 @@ uint8_t OW_Scan(uint8_t *buf, uint8_t num) { if (bit) buf[cnt_num*8 + cnt_byte]|=(1< + * + * 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 2 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include "main.h" +#include "sensors.h" + diff --git a/with_opencm3/sensors.h b/with_opencm3/sensors.h new file mode 100644 index 0000000..b1584aa --- /dev/null +++ b/with_opencm3/sensors.h @@ -0,0 +1,29 @@ +/* + * sensors.h + * + * Copyright 2014 Edward V. Emelianov + * + * 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 2 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +#pragma once +#ifndef __SENSORS_H__ +#define __SENSORS_H__ + +#include "hardware_ini.h" + + + +#endif // __SENSORS_H__ diff --git a/with_opencm3/spi.c b/with_opencm3/spi.c index ccd8f2e..7d3d72c 100644 --- a/with_opencm3/spi.c +++ b/with_opencm3/spi.c @@ -21,6 +21,7 @@ #include "main.h" #include "spi.h" +#include "hardware_ini.h" // Rx/Tx buffer volatile uint8_t SPI_TxBuffer[SPI_BUFFERSIZE]; @@ -32,35 +33,31 @@ volatile uint8_t SPI_datalen = 0; #endif volatile uint8_t SPI_EOT_FLAG = 1; // end of transmission flag, set by interrupt -/* - * Configure SPI port + +uint32_t Current_SPI = SPI1; // this is SPI interface which would b +/** + * Set current SPI to given value */ -void SPI1_init(){ - rcc_periph_clock_enable(RCC_SPI1); - //rcc_periph_clock_enable(RCC_GPIOB); // PB3..5 - rcc_periph_clock_enable(RCC_GPIOA); // PA5..7 - // PA5 - SCK, PA6 - MISO, PA7 - MOSI - gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ, - GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO5 | GPIO7 ); - gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO6); - - spi_reset(SPI1); - /* Set up SPI in Master mode with: - * Clock baud rate: 1/128 of peripheral clock frequency - * Clock polarity: Idle High - * Clock phase: Data valid on 2nd clock pulse - * Data frame format: 8-bit - * Frame format: MSB First - */ - spi_init_master(SPI1, SPI_CR1_BAUDRATE_FPCLK_DIV_128, SPI_CR1_CPOL_CLK_TO_1_WHEN_IDLE, - SPI_CR1_CPHA_CLK_TRANSITION_2, SPI_CR1_DFF_8BIT, SPI_CR1_MSBFIRST); - nvic_enable_irq(NVIC_SPI1_IRQ); // enable SPI interrupt +void switch_SPI(uint32_t SPI){ + Current_SPI = SPI; +} +void SPI_init(){ + switch(Current_SPI){ + case SPI1: + SPI1_init(); + break; + case SPI2: + SPI2_init(); + break; + default: + return; // error + } } //uint32_t read_end; // read timeout /** - * Write data to SPI1 + * Write data to current SPI * @param data - buffer with data * @param len - buffer length (<= DMA_BUFFERSIZE) * @return 0 in case of error (or 1 in case of success) @@ -72,7 +69,7 @@ uint8_t write_SPI(uint8_t *data, uint8_t len){ //DBG("check\r\n"); while(!SPI_EOT_FLAG && Timer < tend); // wait for previous DMA interrupt if(!SPI_EOT_FLAG){ - //DBG("ERR!\r\n"); + DBG("SPI error: no EOT flag!\r\n"); return 0; // error: there's no receiver??? } if(len > SPI_BUFFERSIZE) len = SPI_BUFFERSIZE; @@ -88,9 +85,9 @@ uint8_t write_SPI(uint8_t *data, uint8_t len){ SPI_TxIndex = 0; SPI_datalen = len; // set length of data to transmit // start transmission - enable interrupts - SPI_CR2(SPI1) |= SPI_CR2_TXEIE | SPI_CR2_RXNEIE; //spi_enable_rx_buffer_not_empty_interrupt(SPI1); spi_enable_tx_buffer_empty_interrupt(SPI1); + SPI_CR2(Current_SPI) |= SPI_CR2_TXEIE | SPI_CR2_RXNEIE; //spi_enable_rx_buffer_not_empty_interrupt(SPI1); spi_enable_tx_buffer_empty_interrupt(SPI1); // Enable the SPI peripheral - spi_enable(SPI1); + spi_enable(Current_SPI); #endif // SPI_USE_DMA return 1; } @@ -108,7 +105,7 @@ uint8_t *read_SPI(uint8_t *data, uint8_t len){ //DBG("check\r\n"); while((!SPI_EOT_FLAG || len != SPI_RxIndex) && Timer < tend); if(len != SPI_RxIndex){ - //DBG("ERR\r\n"); + //DBG("SPI error: bad data length\r\n"); return NULL; } //DBG("OK\r\n"); diff --git a/with_opencm3/spi.h b/with_opencm3/spi.h index cca2abf..d08178a 100644 --- a/with_opencm3/spi.h +++ b/with_opencm3/spi.h @@ -31,9 +31,11 @@ typedef enum{ SPI_READ_ERROR } SPI_read_status; -void SPI1_init(); +void SPI_init(); uint8_t write_SPI(uint8_t *data, uint8_t len); SPI_read_status check_SPI(); uint8_t *read_SPI(uint8_t *data, uint8_t len); +void switch_SPI(uint32_t SPI); + #endif // __SPI_H__ diff --git a/with_opencm3/stepper_motors.c b/with_opencm3/stepper_motors.c new file mode 100644 index 0000000..7c17562 --- /dev/null +++ b/with_opencm3/stepper_motors.c @@ -0,0 +1,212 @@ +/* + * stepper_motors.c - moving of stepper motors + * + * Copyright 2014 Edward V. Emelianoff + * + * 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 2 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include "main.h" + +static uint8_t timers_activated[2] = {0, 0}; // flag of activated timers +uint16_t Motor_period[2] = {10000, 10000}; // near 100 steps per second +volatile uint8_t timer_flag[2] = {0,0}; +// amount of steps for each motor +volatile uint32_t Motor_steps[5] = {0, 0, 0, 0, 0}; +// flag of active motor +volatile uint8_t Motor_active[5] = {0, 0, 0, 0, 0}; + + +/** + * Setup stepper motors' timer Tim + * N == 0 for TIM3, == 1 for TIM4 + */ +static void setup_timer(uint8_t N){ + uint32_t Tim; + switch (N){ + case 0: + Tim = TIM3; + nvic_enable_irq(NVIC_TIM3_IRQ); + break; + case 1: + Tim = TIM4; + nvic_enable_irq(NVIC_TIM4_IRQ); + break; + default: + return; + } + timer_reset(Tim); + // timers have frequency of 2MHz, 2 pulse == 1 microstep + // 36MHz of APB1 + timer_set_mode(Tim, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP); + // 72MHz div 36 = 2MHz + timer_set_prescaler(Tim, 35); // prescaler is (div - 1) + timer_continuous_mode(Tim); // automatically reload + timer_enable_preload(Tim); // force changing period + timer_set_period(Tim, Motor_period[N] - 1); + timer_enable_update_event(Tim); + timer_enable_irq(Tim, TIM_DIER_UIE); // update IRQ enable + timer_enable_counter(Tim); + timers_activated[N] = 1; + lastsendfun('3' + N); + MSG(" timer\n"); +} + +/** + * Set up motors pins & activate timers 3 & 4 + * Timer3 gives ticks to motors 1..3 (turrets) + * Timer4 gives ticks to motors 4,5 (long & short stages) + * + * Timers are always work, stopping motors can be done by EN + * Timers simply works as counters, no PWM mode + */ +void steppers_init(){ + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN | + RCC_APB2ENR_IOPBEN | RCC_APB2ENR_IOPCEN | RCC_APB2ENR_IOPDEN | RCC_APB2ENR_IOPEEN); + rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_TIM3EN | RCC_APB1ENR_TIM4EN); + // timer pins + gpio_set_mode(MOTOR_TIM1_PORT, GPIO_MODE_OUTPUT_2_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, MOTOR_TIM1_PIN); + gpio_set_mode(MOTOR_TIM2_PORT, GPIO_MODE_OUTPUT_2_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, MOTOR_TIM2_PIN); + // EN pins + gpio_set_mode(MOTOR_EN_PORT, GPIO_MODE_OUTPUT_2_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, MOROT_EN_MASK); + // DIR pins + gpio_set_mode(MOTOR_DIR_PORT, GPIO_MODE_OUTPUT_2_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, MOROT_DIR_MASK); + setup_timer(0); + setup_timer(1); +} + +/** + * Move motor Motor_number to User_value steps + */ +void move_motor(uint8_t num, int32_t steps){ + if(steps == 0) return; + // check whether motor is moving + if(Motor_active[num]){ + MSG("err: moving\r\n"); + return; + } + if(steps < 0){ + steps = -steps; + gpio_set(MOTOR_DIR_PORT, MOTOR_DIR_PIN(num)); // set DIR bit to rotate ccw + }else + gpio_clear(MOTOR_DIR_PORT, MOTOR_DIR_PIN(num)); // reset DIR bit + Motor_steps[num] = steps << 4; // multiply by 16 to get usteps count + Motor_active[num] = 1; + gpio_set(MOTOR_EN_PORT, MOTOR_EN_PIN(num)); // activate motor +} + +void stop_motor(uint8_t num){ + if(!Motor_active[num]) return; + MSG("stop motor "); + lastsendfun('0' + num); + MSG("\r\n"); + gpio_clear(MOTOR_EN_PORT, MOTOR_EN_PIN(num)); + Motor_active[num] = 0; +} + +/** + * Check flags set by timers & do next: + * - decrease step counter if it isn't zero; + * - stop motor if counter is zero but motor still active + */ +void process_stepper_motors(){ + int i, j; + const uint32_t ports[] = {MOTOR_TIM1_PORT, MOTOR_TIM2_PORT}; + const uint32_t pins[] = {MOTOR_TIM1_PIN, MOTOR_TIM2_PIN}; + const uint8_t startno[] = {0, 3}; + const uint8_t stopno[] = {3, 5}; + for(j = 0; j < 2; j++){ + if(timer_flag[j]){ + timer_flag[j] = 0; + gpio_toggle(ports[j], pins[j]); // change clock state + if(gpio_get(ports[j], pins[j])){ // positive pulse - next microstep + for(i = startno[j]; i < stopno[j]; i++){ // check motors + if(Motor_steps[i]) Motor_steps[i]--; + else if(Motor_active[i]){ // stop motor - all done + stop_motor(i); + } + } + } + } + } +} + +/** + * Stop timers; turn off motor voltage + * +void stop_timer(){ + // disable IRQs & stop timer + TIM_Cmd(SM_Timer, DISABLE); + TIM_ITConfig(SM_Timer, TIM_IT_Update, DISABLE); + // turn off power + SM_EN_GPIOx->BRR = SM_EN_PINS; // reset all EN bits + SM_PUL_GPIOx->BRR = SM_PUL_PIN; // reset signal on PUL + timers_activated = 0; + Motor_steps = 0; +}*/ + +/** + * Sets motor period to user value & refresh timer + * @param num - number of motor + * @param period - period of one STEP in microseconds + */ +void set_motor_period(uint8_t num, uint16_t period){ + uint32_t Tim, N; + switch (num){ + case 1: + case 2: + case 3: + Tim = TIM3; + N = 0; + break; + case 4: + case 5: + Tim = TIM4; + N = 1; + break; + default: + MSG("err: bad motor"); + return; + } + period >>= 4; // divide by 4 to get 16usteps for one step + if(period == 0) Motor_period[N] = 1; + else Motor_period[N] = period; + if(!timers_activated[N]) setup_timer(N); + else timer_set_period(Tim, period); +} + +/* + * Interrupts: just set flag + */ +void tim3_isr(){ + if(timer_get_flag(TIM3, TIM_SR_UIF)){ + // Clear compare interrupt flag + timer_clear_flag(TIM3, TIM_SR_UIF); + timer_flag[0] = 1; + } +} + +void tim4_isr(){ + if(timer_get_flag(TIM4, TIM_SR_UIF)){ + // Clear compare interrupt flag + timer_clear_flag(TIM4, TIM_SR_UIF); + timer_flag[1] = 1; + } +} diff --git a/with_opencm3/stepper_motors.h b/with_opencm3/stepper_motors.h new file mode 100644 index 0000000..121ab98 --- /dev/null +++ b/with_opencm3/stepper_motors.h @@ -0,0 +1,33 @@ +/* + * stepper_motors.h + * + * Copyright 2014 Edward V. Emelianoff + * + * 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 2 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +#pragma once +#ifndef __STEPPER_MOTORS_H__ +#define __STEPPER_MOTORS_H__ + +#include + +void steppers_init(); +void process_stepper_motors(); +void move_motor(uint8_t num, int32_t steps); +void stop_motor(uint8_t num); +void set_motor_period(uint8_t num, uint16_t period); + +#endif // __STEPPER_MOTORS_H__ diff --git a/with_opencm3/sync.c b/with_opencm3/sync.c new file mode 100644 index 0000000..12e6980 --- /dev/null +++ b/with_opencm3/sync.c @@ -0,0 +1,88 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2012 Fergus Noble + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#include + +/* DMB is supported on CM0 */ +void __dmb() +{ + __asm__ volatile ("dmb"); +} + +/* Those are defined only on CM3 or CM4 */ +#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) + +uint32_t __ldrex(volatile uint32_t *addr) +{ + uint32_t res; + __asm__ volatile ("ldrex %0, [%1]" : "=r" (res) : "r" (addr)); + return res; +} + +uint32_t __strex(uint32_t val, volatile uint32_t *addr) +{ + uint32_t res; + __asm__ volatile ("strex %0, %2, [%1]" + : "=&r" (res) : "r" (addr), "r" (val)); + return res; +} + +void mutex_lock(mutex_t *m) +{ + uint32_t status = 0; + + do { + /* Wait until the mutex is unlocked. */ + while (__ldrex(m) != MUTEX_UNLOCKED); + + /* Try to acquire it. */ + status = __strex(MUTEX_LOCKED, m); + + /* Did we get it? If not then try again. */ + } while (status != 0); + + /* Execute the mysterious Data Memory Barrier instruction! */ + __dmb(); +} + +void mutex_unlock(mutex_t *m) +{ + /* Ensure accesses to protected resource are finished */ + __dmb(); + + /* Free the lock. */ + *m = MUTEX_UNLOCKED; +} + +/* + * Try to lock mutex + * if it's already locked or there was error in STREX, return MUTEX_LOCKED + * else return MUTEX_UNLOCKED + */ +mutex_t mutex_trylock(mutex_t *m){ + uint32_t status = 0; + mutex_t old_lock = __ldrex(m); // get mutex value + // set mutex + status = __strex(MUTEX_LOCKED, m); + if(status == 0) __dmb(); + else old_lock = MUTEX_LOCKED; + return old_lock; +} + +#endif diff --git a/with_opencm3/sync.h b/with_opencm3/sync.h new file mode 100644 index 0000000..f3fc7af --- /dev/null +++ b/with_opencm3/sync.h @@ -0,0 +1,53 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2012 Fergus Noble + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#ifndef LIBOPENCM3_CM3_SYNC_H +#define LIBOPENCM3_CM3_SYNC_H + +void __dmb(void); + +/* Implements synchronisation primitives as discussed in the ARM document + * DHT0008A (ID081709) "ARM Synchronization Primitives" and the ARM v7-M + * Architecture Reference Manual. +*/ + +/* --- Exclusive load and store instructions ------------------------------- */ + +/* Those are defined only on CM3 or CM4 */ +#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) + +uint32_t __ldrex(volatile uint32_t *addr); +uint32_t __strex(uint32_t val, volatile uint32_t *addr); + +/* --- Convenience functions ----------------------------------------------- */ + +/* Here we implement some simple synchronisation primitives. */ + +typedef uint32_t mutex_t; + +#define MUTEX_UNLOCKED 0 +#define MUTEX_LOCKED 1 + +void mutex_lock(mutex_t *m); +void mutex_unlock(mutex_t *m); +mutex_t mutex_trylock(mutex_t *m); + +#endif + +#endif diff --git a/with_opencm3/uart.c b/with_opencm3/uart.c index 4fbf8a8..d324588 100644 --- a/with_opencm3/uart.c +++ b/with_opencm3/uart.c @@ -74,7 +74,7 @@ void UART_setspeed(uint32_t UART, struct usb_cdc_line_coding *lc){ void UART_init(uint32_t UART){ uint32_t irq, rcc, rccgpio, gpioport, gpiopin; switch(UART){ - case USART2: + case USART2: // 1-wire irq = NVIC_USART2_IRQ; // interrupt for given USART rcc = RCC_USART2; // RCC timing of USART rccgpio = RCC_GPIOA; // RCC timing of GPIO pin (for output) @@ -84,7 +84,7 @@ void UART_init(uint32_t UART){ gpioport = GPIO_BANK_USART2_TX; gpiopin = GPIO_USART2_TX; break; - case USART3: + case USART3: // without remapping irq = NVIC_USART3_IRQ; rcc = RCC_USART3; rccgpio = RCC_GPIOB; @@ -106,10 +106,19 @@ void UART_init(uint32_t UART){ // enable clocking rcc_periph_clock_enable(RCC_AFIO); // alternate functions rcc_periph_clock_enable(rcc); // USART - rcc_periph_clock_enable(rccgpio); // output pin + rcc_periph_clock_enable(rccgpio); // GPIO pins // enable output pin - gpio_set_mode(gpioport, GPIO_MODE_OUTPUT_50_MHZ, - GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, gpiopin); + if(UART == OW_USART_X){ // one wire + // TX: open-drain output + gpio_set_mode(gpioport, GPIO_MODE_OUTPUT_50_MHZ, + GPIO_CNF_OUTPUT_ALTFN_OPENDRAIN, gpiopin); + // RX: floating input + gpio_set_mode(OW_RX_PORT, GPIO_MODE_INPUT, + GPIO_CNF_INPUT_FLOAT, OW_RX_PIN); + }else{ + gpio_set_mode(gpioport, GPIO_MODE_OUTPUT_50_MHZ, + GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, gpiopin); + } // enable IRQ nvic_enable_irq(irq); UART_setspeed(UART, NULL); diff --git a/with_opencm3/uart.h b/with_opencm3/uart.h index 66ea2e9..b775147 100644 --- a/with_opencm3/uart.h +++ b/with_opencm3/uart.h @@ -24,7 +24,7 @@ #define __UART_H__ // Size of buffers -#define UART_TX_DATA_SIZE 64 +#define UART_TX_DATA_SIZE 128 typedef struct { uint8_t buf[UART_TX_DATA_SIZE]; diff --git a/with_opencm3/user_proto.c b/with_opencm3/user_proto.c index bd02379..7be8393 100644 --- a/with_opencm3/user_proto.c +++ b/with_opencm3/user_proto.c @@ -26,6 +26,8 @@ // integer value given by user static volatile int32_t User_value = 0; +// number of motor to process +static volatile uint8_t active_motor = 6; // last active send function - to post "anonymous" replies sendfun lastsendfun = usb_send; // make it usb_send by default (to prevent suspension) // flag: !=0 when user value reading ends - for character terminals @@ -62,7 +64,8 @@ void print_ad_vals(sendfun s){ void parce_incoming_buf(char *buf, int len, sendfun s){ uint8_t command; - int i = 0, j; + uint8_t onewire_addr[8]; + int i = 0, j, m; lastsendfun = s; if(Uval_ready == UVAL_START){ // we are in process of user's value reading i += read_int(buf, len); @@ -78,11 +81,40 @@ void parce_incoming_buf(char *buf, int len, sendfun s){ for(; i < len; i++){ command = buf[i]; if(!command) continue; // omit zero - switch (command){ - case '1': // single conversion + if(command >= '0' && command <= '4'){ // stepper motors + active_motor = command - '0'; + I = stepper_proc; + READINT(); + }else switch (command){ + case 'P': + run_dmatimer(); + break; + case 'x': // set period of TIM1 (motors 1..3) + active_motor = 1; + I = set_timr; + READINT(); + break; + case 'X': // set period of TIM2 (motors 4,5) + active_motor = 4; + I = set_timr; + READINT(); + break; + case 'B': // stop all motors + for(m = 0; m < 5; m++) + stop_motor(m); + break; + case 'W': // scan for one 1-wire device + if(1 == OW_Scan(onewire_addr, 1)){ + P("found 1-wire: ", s); + print_hex(onewire_addr, 8, s); + }else + P("1-wire error",s ); + P("\r\n", s); + break; + case 'S': // single conversion doubleconv = 0; break; - case '2': // double conversion + case 'D': // double conversion doubleconv = 1; break; case 'A': // show ADC value @@ -94,19 +126,12 @@ void parce_incoming_buf(char *buf, int len, sendfun s){ } newline(s); break; - case 'b': // turn LED off - gpio_set(GPIOC, GPIO12); - break; - case 'B': // turn LED on - gpio_clear(GPIOC, GPIO12); - break; - case 'I': // read & print integer value - I = process_int; - READINT(); - break; case 'i': // init AD7794 AD7794_init(); break; + case 'I': // turn off flag AD7794 + ad7794_on = 0; + break; case '+': // user check number value & confirm it's right if(Uval_ready == UVAL_PRINTED) Uval_ready = UVAL_CHECKED; else WRONG_COMMAND(); @@ -140,9 +165,9 @@ void parce_incoming_buf(char *buf, int len, sendfun s){ print_time(s); newline(s); break; - case 'U': // test: init USART1 + /* case 'U': // test: init USART1 UART_init(USART1); - break; + break; */ case '\n': // show newline as is break; case '\r': @@ -210,6 +235,27 @@ int read_int(char *buf, int cnt){ return readed; } +/** + * Print buff as hex values + * @param buf - buffer to print + * @param l - buf length + * @param s - function to send a byte + */ +void print_hex(uint8_t *buff, uint8_t l, sendfun s){ + void putc(uint8_t c){ + if(c < 10) + s(c + '0'); + else + s(c + 'a' - 10); + } + s('0'); s('x'); // prefix 0x + while(l--){ + putc(buff[l] >> 4); + putc(buff[l] & 0x0f); + } +} + + /** * Print decimal integer value * @param N - value to print @@ -230,12 +276,14 @@ void print_int(int32_t N, sendfun s){ }else s('0'); } +/* void process_int(int32_t v, sendfun s){ newline(s); P("You have entered a value ", s); print_int(v, s); newline(s); } +*/ void set_ADC_gain(int32_t v, sendfun s){ if(ad7794_on){ @@ -246,3 +294,34 @@ void set_ADC_gain(int32_t v, sendfun s){ AD7794_calibration(0); } } + +/** + * Process stepper + * @param v - user value + * @param s - active sendfunction + */ +void stepper_proc(int32_t v, sendfun s){ + if(active_motor > 4){ + P("wrong motor number\r\n", s); + return; // error + } + MSG("move "); + lastsendfun('0' + active_motor); + MSG(" to "); + print_int(v, lastsendfun); + MSG("\r\n"); + move_motor(active_motor, v); + active_motor = 6; +} + +void set_timr(int32_t v, sendfun s){ + if(active_motor > 4){ + P("wrong motor number\r\n", s); + return; // error + } + MSG("set period: "); + print_int(v, lastsendfun); + MSG("\r\n"); + set_motor_period(active_motor, (uint16_t)v); + active_motor = 6; +} diff --git a/with_opencm3/user_proto.h b/with_opencm3/user_proto.h index 77cb3f1..f6b28d7 100644 --- a/with_opencm3/user_proto.h +++ b/with_opencm3/user_proto.h @@ -50,8 +50,11 @@ void print_int(int32_t N, sendfun s); void parce_incoming_buf(char *buf, int len, sendfun s); -void process_int(int32_t v, sendfun s); +// void process_int(int32_t v, sendfun s); void set_ADC_gain(int32_t v, sendfun s); void print_ad_vals(sendfun s); +void stepper_proc(int32_t v, sendfun s); +void set_timr(int32_t v, sendfun s); +void print_hex(uint8_t *buff, uint8_t l, sendfun s); #endif // __USER_PROTO_H__