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 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
|
# Reading and writing special function registers
Features of microcontrollers ranging from I/O operations to ADC reading and I2C communications are all configured by toggling and reading bits in variables called Special Function Registers (SFR)
For example, in the ATMEGA32 microcontroller, the DDRB register (Data direction Register for B pins PB0 - PB7) , is used to set which pins on Port B are output, and which are input. This can be done by writing an 8-bit number(0 - 255) to DDRB , where each bit controls one of the pins from PB0 to PB7.
DDRB = 255 (binary 11111111) implies all pins will be output type. DDRB = 160 (101000000) implies PB7 and PB5 will be output type, and rest will be input.
Similarly, PORTB register is used to turn an output HIGH(5V), or LOW(0V/Ground)

PB5 and PB7 set to Output type (DDRB=160), and made HIGH(PORTB=160).
### Test this with a simple code to turn on an LED connected to PB3
=== "Python Code"
```python
from kuttyPy import * # automatically connects to an available device.
setReg('DDRB',8) # PB3 made output. 0b00001000 = 8
setReg('PORTB', 8) #PB3 to 5 Volt supply. RED LED turns on
```
=== "C equivalent"
```C hl_lines="1"
/* Compile with AVR-GCC for atmega32, and upload with avrdude/kuttypy-gui */
#include <avr/io.h>
int main (void) {
DDRB = 8; // Data Direction Register for port B
PORTB = 8; // PB3 HIGH
}
return 0;
}
```
## Python Functions for basic register access
### setting and reading register values
=== "setReg"
```python hl_lines="1"
def setReg(Register Name, Value)
writes a value to a REGISTER defined in the datasheet of the processor
Register Name : a string representing the register. e.g. 'DDRB', 'ADMUX' etc
Value: an integer between 0 and 255 , because atmega32 is an 8 bit microcontroller.
return: True if success
```
=== "getReg"
```python hl_lines="1"
def getReg(Register Name)
reads a value frm a REGISTER defined in the datasheet of the processor
Register Name : a string representing the register. e.g. 'PINB', 'ADCL', 'ADCH' etc
return: Contents of the register. an integer between 0 and 255
```
=== "Example"
```python hl_lines="1"
# Read value from Analog to Digital converter(ADC) channel 0 (PA0)
from kuttyPy import *
setReg('ADMUX', (1<<6) | 0) #REF_AVCC | Channel 0
setReg('ADCSRA', 196) #Set ADC conversion speeds, and enable it. Refer to the ATMEGA32 datasheet for details.
cl = getReg('ADCL') #LSB 8 bits
ch = getReg('ADCH') # MSB 2 bits
print( (ch<<8)|cl ) # Combine the two to make a 10 bit number, and print to the screen
```
You can also twiddle bits on various registers inside the "Registers" tab to watch
changes in real time. In the animation below, the ADC is being continuously read.

=== "readADC"
```python hl_lines="1"
def readADC(channel)
reads a voltage value from the specified channel, and returns it
channel : 0 to 7
return: 10 bit number( an integer between 0 and 1023 )
```
=== "data logger example with matplotlib"
```python hl_lines="1"
# Read values from Analog to Digital converter(ADC)
# channel 5 (PA5), and plot them
import time
from kuttyPy import *
from matplotlib import pyplot as plt
setReg('ADMUX', (1<<6) | 5) #REF_AVCC | Channel 5
for a in range(50):
setReg('ADCSRA', 196)
cl = getReg('ADCL')
ch = getReg('ADCH')
plt.scatter(a, (ch<<8)|cl ,s=5)
plt.pause(0.01) #Wait 10 mS
```
## Embedded iPython Console
In the scripting tab, there is an option to launch the ipython console. This
is a quick way to access the python functions from the GUI itself.
The kuttyPy instance in this window is called `kp` , so you can
use functions such as `kp.setReg` , `kp.MPU6050_init` etc.
TAB based autocompletion and inline help is also available.
!!! tip "Screenshot"

## Total list of defined registers for ATMEGA32
```python
UBRRL = 0X29,
UCSRB = 0X2A,
UCSRA = 0X2B,
UDR = 0X2C,
SPCR = 0X2D,
SPSR = 0X2E,
SPDR = 0X2F,
PIND = 0x30, # Port D input
DDRD = 0x31, # Port D direction
PORTD = 0x32, # Port D output
PINC = 0x33,
DDRC = 0x34,
PORTC = 0x35,
PINB = 0x36,
DDRB = 0x37,
PORTB = 0x38,
PINA = 0x39,
DDRA = 0x3A,
PORTA = 0x3B,
EECR = 0X3C,
EEDR = 0X3D,
EEARL = 0X3E,
EEARH = 0X3F,
TWBR = 0X20,
TWSR = 0X21,
TWAR = 0X22,
TWDR = 0X23,
ADCL = 0X24, # ADC data
ADCH = 0X25,
ADCSRA = 0X26, # ADC status/control
ADMUX = 0X27, # ADC channel, reference
ACSR = 0X28,
OCR2 = 0X43, # Timer/Counter 2 Output Compare Reg
TCNT2 = 0X44 , # Counter2
TCCR2 = 0x45, # Timer/Counter 2 control reg
ICR1L = 0X46,
ICR1H = 0X47,
OCR1BL = 0X48,
OCR1BH = 0X49,
OCR1AL = 0X4A,
OCR1AH = 0X4B,
TCNT1L = 0X4C,
TCNT1H = 0X4D,
TCCR1B = 0X4E,
TCCR1A = 0x4F,
SFIOR = 0X50,
TCNT0 = 0x52 , # Timer/ Counter 0
TCCR0 = 0x53,
MCUCSR = 0X54,
MCUCR = 0X55,
TWCR = 0X56,
SPMCR = 0X57,
TIFR = 0X58,
TIMSK = 0X59,
GIFR = 0X5A,
GICR = 0X5B,
OCR0 = 0x5C,
SPL = 0X5D,
SPH = 0x5E,
SREG = 0X5F
```
|