MiK-Music 
The new home of MiK-Music's music electronics DIY site

[ 6 comments ]   |  [ 0 trackbacks ]   |  permalink  |  related link
STM32F4 Basics: Timers (Part 1) 
These STM32F4 Basics posts aren't really tutorials so much as they are slightly-organized notes with short and contrived examples. Many aspects and nuances are ignored. Look through the documentation and headers referenced throughout this post to fill in the gaps. The Timer chapters in RM0090 would be a good place to start.


[ add comment ]   |  [ 0 trackbacks ]   |  permalink  |  related link
Compute prescaler/counter values for a MCU based oscillator, with Python 

'''
this program helps to compute note frequencies for a MCU based oscillator
where the selection of the optimal prescaller and counter value is
needed.

program output is a C array with counter register values.

each next note is larger than the one before it by the same ratio (the
twelfth root of 2, which is 1.05946309435929526456182529494634170077
9204317494... )

please check http://www.math.niu.edu/~rusin/uses-mat ... requencies
for list of frequencies.

to achieve excellent precission you may convert program to use numpy.

with numpy:

>>> def root(n, r):
... from numpy import roots
... return roots([1]+[0]*(r-1)+[-n])
...
root(2, r=12)[0]
(-1.0594630943592918+0j)
'''
DEBUG = False

notes = [
'C ', 'C#', 'D ', 'D#', 'E ', 'F ', 'F#', 'G ', 'G#', 'A ', 'A#', 'B ' ]

default_clock = 84000000.0 # chip clock
start_tone_frequency = 32.703195662574829 # C0
start_tone_midi = 21
stop_tone_frequency = 4186.01 # max desired frequency C8

twelfth_root_of_two = 1.059463094359295264561825294946341700779204317494

clock_frequencies = []
round_list = []
note_list = []

for clock_prescaler in range( 1, int( default_clock ) ):

if default_clock % clock_prescaler == 0:
if default_clock / clock_prescaler > stop_tone_frequency:
clock_frequencies.append( \
( default_clock / clock_prescaler, clock_prescaler ) )

elif DEBUG:
print "frequecy is less than the max desired frequency"

elif DEBUG:
print "divider does not produce round result"

print "---------------------------------------------------------------"
print "suitable frequencies: ", clock_frequencies


for clock_base_hz, clock_prescaler in clock_frequencies:

f = start_tone_frequency
f_midi_note = start_tone_midi

divider_is_less_than_oxffff = True
most_significant_frequency_gap = 0

print "---------------------------------------------------------------"
print "values for osc_base: ", clock_base_hz
print "clock_base_hz octave note f real_frequency tick_counter"

for octave in xrange( 1, 8 ):
for note in notes:

current_note_divider_is_less_than_oxffff = True

if clock_base_hz / f > 0xffff:
current_note_divider_is_less_than_oxffff = False
divider_is_less_than_oxffff = False

counter_value = round( clock_base_hz / f )
real_frequency = clock_base_hz / counter_value
real_frequency_gap = abs( real_frequency - f )

if most_significant_frequency_gap < real_frequency_gap:
most_significant_frequency_gap = real_frequency_gap

print clock_base_hz, octave, note, f, real_frequency_gap, \
counter_value

note_list.append( ( ( clock_base_hz, clock_prescaler ), \
( octave, note, f_midi_note, counter_value, f,
real_frequency, real_frequency - f, \
current_note_divider_is_less_than_oxffff ) ) )

f = f * twelfth_root_of_two
f_midi_note += 1

round_list.append( ( clock_base_hz , clock_prescaler, \
most_significant_frequency_gap, divider_is_less_than_oxffff ) )

suitable_frequencies_sorted = sorted( round_list, key=lambda l: l[2] )

print "---------------------------------------------------------------"
print "suitable frequencies (sorted by total inaccuracy): "
print "True/False shows if 16-bit long counter can be used"
for frequency in suitable_frequencies_sorted:
print frequency

print "---------------------------------------------------------------"
freq_to_list = input("Enter base freq to list notes: ")

print "octave note midi_note divider f real_f frequency_gap"
for record, values in note_list:
if record[0] == freq_to_list:
print values


print "---------------------------------------------------------------"
c_array_legend = ""
c_array_clock_prescalers = ""
c_array_clock_dividers = ""
c_count = 0


''' based on selected frequency create list of counter values '''
for record, values in note_list:
if record[0] == freq_to_list:
c_array_clock_prescalers += "%d, " % record[1]
c_count += 1

print "// osc: prescalers"
print "uint16_t clock_prescaler[%d] = { %s };" \
% ( c_count, c_array_clock_prescalers[:-2] )

''' example of values in note list:

oct note midi countr real_f computed_f f_error 0xffff
(7, 'B ', 104, 506.0, 7902.132820098011, 7905.138339920949, 3.0055198229383677, True)
'''

''' based on selected frequency create list of counter values '''
for record, values in note_list:
if record[0] == freq_to_list:
c_array_clock_dividers += "%d, " % values[3]

print "// osc: counters"
print "uint16_t clock_counter[%d] = { %s };" \
% ( c_count, c_array_clock_dividers[:-2] )

''' based on selected frequency create list of note detailed legends '''
for record, values in note_list:
if record[0] == freq_to_list:
c_array_legend += '"%s%s(%s) c: %s\\nfreq: %s", ' \
% ( values[0], values[1], \
values[2], values[3], \
values[4] )

print "// osc: legends"
print "char * clock_legend[%d] = { %s };" % ( c_count, c_array_legend[:-2] )

print


[ 6 comments ]   |  [ 0 trackbacks ]   |  permalink
Running Python on Windows, installing libs requires SETUPTOOLS, PIP and compiler 
Flying in the face of its 'batteries included' motto, Python ships without a package manager. Adding insult to injury, Pip is ironically difficult to install. The official documentation tells users to install Pip and each its dependencies from source. That's tedious for the experienced, and tactless to newbies.


from: http://stackoverflow.com/questions/4750 ... on-windows

Unofficial Windows Binaries for Python Extension Packages


[ add comment ]   |  [ 0 trackbacks ]   |  permalink  |  related link
Hairless MIDI 
Hairless MIDI<->Serial Bridge is the easiest way to connect serial devices (like Arduinos) to send and receive MIDI signals. 100% Free Software. For Mac OS X, Windows & Linux.

[ add comment ]   |  [ 0 trackbacks ]   |  permalink  |  related link
Micro Python: Python for microcontrollers 
The Python language made lean and fast to run on microcontrollers. For beginners and experts, control your electronic project with ease.


[ 2 comments ]   |  [ 0 trackbacks ]   |  permalink  |  related link
STM32f4 Discovery driver using I2C Interface to communicate with 1602/HD44780 LCD 
The code below is working STM32f4 driver for an 1602 LCD equipped with HD44780 controller which uses IIC I2C Serial Interface Board Module.



useful links: physical connections, IIC I2C Serial Interface

support_nej.h:
#include <stdint.h>

void lcd_i2c_init( void );
void lcd_i2c_pulse( uint8_t _data );

void lcd_command( uint8_t value );
void lcd_data( uint8_t value );
void lcd_send( uint8_t value, uint8_t mode );

void delay_ms( uint32_t _delay );
void lcd_command_clear( void );
void lcd_simple_print( const char *str );
void lcd_printf( const char *format, ... );

void lcd_i2c_pulse( uint8_t _data );



support_nej.c:
// support for 1602 LCD display ( 2 x 16 characters )
// equipped with HD44780 controller.
// tested on STM32f4 Discovery
//

#include <stdio.h>
#include <stdbool.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdint.h>

#include "support_nej.h"
#include "support_nej_i2c.h"
#include "support_nej_lcd.h"

#define I2C_LCD_SLAVE_ADDRESS 0x20

// Keil compiler does not support bit notation (aka 0b00..)
// the following define adds the missing functionality
#define BIN_TO_BYTE(b7,b6,b5,b4,b3,b2,b1,b0) \
((b7 << 7)+(b6 << 6)+\
(b5 << 5)+(b4 << 4)+\
(b3 << 3)+(b2 << 2)+\
(b1 << 1)+b0)


// LCD definitions
//
//
//

// HD44780 controller functions
#define LCD_CLEARDISPLAY 0x01
#define LCD_RETURNHOME 0x02
#define LCD_ENTRYMODESET 0x04
#define LCD_DISPLAYCONTROL 0x08
#define LCD_CURSORSHIFT 0x10
#define LCD_FUNCTIONSET 0x20
#define LCD_SETCGRAMADDR 0x40
#define LCD_SETDDRAMADDR 0x80

// flags for LCD_ENTRYMODESET
#define LCD_ENTRYRIGHT 0x00
#define LCD_ENTRYLEFT 0x02
#define LCD_ENTRYSHIFTINCREMENT 0x01
#define LCD_ENTRYSHIFTDECREMENT 0x00

// flags for LCD_DISPLAYCONTROL
#define LCD_DISPLAYON 0x04
#define LCD_DISPLAYOFF 0x00
#define LCD_CURSORON 0x02
#define LCD_CURSOROFF 0x00
#define LCD_BLINKON 0x01
#define LCD_BLINKOFF 0x00

// flags for LCD_CURSORSHIFT
#define LCD_DISPLAYMOVE 0x08
#define LCD_CURSORMOVE 0x00
#define LCD_MOVERIGHT 0x04
#define LCD_MOVELEFT 0x00

// flags for LCD_FUNCTIONSET
#define LCD_8BITMODE 0x10
#define LCD_4BITMODE 0x00
#define LCD_1LINE 0x00
#define LCD_2LINE 0x08
#define LCD_5x10DOTS 0x04
#define LCD_5x8DOTS 0x00


// master pins
#define LCD_BACKLIGHT_ON BIN_TO_BYTE(0,0,0,0,0,0,0,0) // ON = data is LOW
#define LCD_BACKLIGHT_OFF BIN_TO_BYTE(1,0,0,0,0,0,0,0) // OFF = data is HIGH

#define LCD_RS_DATA BIN_TO_BYTE(0,1,0,0,0,0,0,0) // DATA (write to CGRAM/DDRAM)
#define LCD_RS_COMMAND BIN_TO_BYTE(0,0,0,0,0,0,0,0) // COMMANDS

#define LCD_RW_HIGH BIN_TO_BYTE(0,0,1,0,0,0,0,0) // READ from LCD
#define LCD_RW_LOW BIN_TO_BYTE(0,0,0,0,0,0,0,0) // WRITE to LCD (character or command)

#define LCD_PULSE_HIGH BIN_TO_BYTE(0,0,0,1,0,0,0,0) // Enable Pulse on pin 6
#define LCD_PULSE_LOW BIN_TO_BYTE(0,0,0,0,0,0,0,0) // when pulse goes from high to low the data is read


// COMMANDS: set DDRAM address ( display 2 x 16 )
#define LCD_CURSOR_LINE_MAX 15
#define LCD_CURSOR_TO_LINE_1 BIN_TO_BYTE(1,0,0,0,0,0,0,0)
#define LCD_CURSOR_TO_LINE_2 BIN_TO_BYTE(1,1,0,0,0,0,0,0)


// ASCII definitions for CR (\r) and LF (\n)
// used in printf
#define ASCII_CARRIAGE_RETURN 0x0d
#define ASCII_LINE_FEED 0x0a


// small buffer for prinf formatting
#define PRINT_BUFFER_SIZE 64


// lcd_simple_print and lcd_printf are function for
// text output on the i2c connected display
//
//
void lcd_simple_print( const char *str )
{
uint8_t _cursor_position = 0;

lcd_command_clear();

while( *str ) {

_cursor_position++;
if( _cursor_position > LCD_CURSOR_LINE_MAX | *str == ASCII_LINE_FEED )
{
lcd_command( LCD_CURSOR_TO_LINE_2 );
_cursor_position = 0;
str++;
} else
{
lcd_data( *str );
str++;
}

}
}


void lcd_printf( const char *format, ... )
{
va_list args;
char *buf = ( char *) malloc( PRINT_BUFFER_SIZE * sizeof( char ) );

if( buf != 0 )
{
va_start( args, format );

if( vsnprintf( buf, PRINT_BUFFER_SIZE * sizeof( char ), format, args ) > 0 )
{
lcd_simple_print( buf );
} else
{
lcd_simple_print( buf );
lcd_simple_print( "lcd_printf: maxlen \
character limit was reached or some other error, \
such as an invalid format specification\n" );
}

va_end( args );
free( buf );

} else
{
lcd_simple_print( "lcd_printf: not enough memory\n" );
}
}


// some simple delay, should use timer
//
void delay_ms( uint32_t _time )
{
_time = _time * 420;

while( _time-- )
{
}
}


// abstract functions
// concept taken from arduino I2C LCD library
//
//
void lcd_command( uint8_t value )
{
lcd_send( value, LCD_RS_COMMAND );
}

void lcd_command_clear( void )
{
lcd_command( LCD_CLEARDISPLAY );
delay_ms( 100 );
}

void lcd_data( uint8_t value )
{
lcd_send( value, LCD_RS_DATA );
}


// convert function for 4-bit communication
// writes either command or data
//
//
void lcd_send( uint8_t value, uint8_t mode )
{
uint8_t high_nibble = ( value>>4 ) & 0x0f;
uint8_t low_nibble = ( value ) & 0x0f;

lcd_i2c_pulse( high_nibble | mode );
lcd_i2c_pulse( low_nibble | mode );
}


// the "pulse" function simulates the ramp ON/OFF
// the controller reads data when the LCD_PULSE pin
// goes from HIGH to LOW
//
void lcd_i2c_pulse( uint8_t _data )
{
I2C_start( I2C1, I2C_LCD_SLAVE_ADDRESS<<1, I2C_Direction_Transmitter );
I2C_write( I2C1, (uint8_t) ( _data ) );
I2C_stop( I2C1 );

I2C_start( I2C1, I2C_LCD_SLAVE_ADDRESS<<1, I2C_Direction_Transmitter );
I2C_write( I2C1, (uint8_t) ( _data ) | LCD_PULSE_HIGH );
I2C_stop( I2C1 );

I2C_start( I2C1, I2C_LCD_SLAVE_ADDRESS<<1, I2C_Direction_Transmitter );
I2C_write( I2C1, (uint8_t) ( _data ) );
I2C_stop( I2C1 );
}


// sets the controller: 4-bit communication
// interaction with 1602 LCD
//
//
void lcd_i2c_init( void )
{
// switch controller to 8bit mode, regardless the mode
// the controller is in. there should be waits added
// 5ms for command writes and 200us for data writes.

lcd_i2c_pulse( 0x03 );
lcd_i2c_pulse( 0x03 );

// LCD in 8-bit mode

lcd_i2c_pulse( 0x03 );

// switch to 4-bit mode
lcd_i2c_pulse( 0x02 );

// controller is in 4-bit mode, configure its behaviour

lcd_command( LCD_FUNCTIONSET | \
LCD_4BITMODE | LCD_2LINE | LCD_5x8DOTS );

lcd_command( LCD_DISPLAYCONTROL | \
LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF );

lcd_command( LCD_ENTRYMODESET | \
LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT );
};


[ 180 comments ]   |  [ 0 trackbacks ]   |  permalink
STM32F10xx, STM32F2xx, STM32F4xx and STM32L1xx I2C Communication peripheral application library (CPAL) (UM1029)  
The aim of this application note is to provide I2C firmware optimized examples based on polling, interrupts and DMA, covering the four I2C communication modes available in the STM32F10xxx, that is, slave transmitter, slave receiver, master transmitter and master receiver and to provide recommendations on the correct use of the I2C peripheral.

[ 9 comments ]   |  [ 0 trackbacks ]   |  permalink  |  related link
Four-Bit D/A Converter  


[ 10 comments ]   |  [ 0 trackbacks ]   |  permalink  |  related link
pulse timers  
/* Time 2 base configuration 10ms */
TIM_TimeBaseStructure.TIM_Period = 9999;
TIM_TimeBaseStructure.TIM_Prescaler = 72;
TIM_TimeBaseStructure.TIM_ClockDivision =TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

Period calculation:

72MHz / 72 = 1MHz or 1µs period unit.
1µs + 9999 x (1µs) = 10ms


http://guyvo-cortex.blogspot.cz/2009/04 ... imers.html



void TIM4_Configuration(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

// TIM_TimeBaseStructure.TIM_Prescaler = (800 * 2) - 1; // 8 MHz clock source, 8000 for 2 ms, 800 for 0.2 ms ticks
TIM_TimeBaseStructure.TIM_Prescaler = (7200 * 2) - 1; // 72 MHz clock source, 0.2 ms ticks

TIM_TimeBaseStructure.TIM_Period = 50000 - 1; // 0.2 ms units, 10 second update
TIM_TimeBaseStructure.TIM_ClockDivision = 1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);

// TIM4 enable counter
TIM_Cmd(TIM4, ENABLE);

// Clear pending update interrupt
TIM_ClearITPendingBit(TIM4, TIM_IT_Update);

// Enable interrupt on update
TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);
}


https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=https%3a%2f%2fmy.st.com%2fpublic%2fSTe2ecommunities%2fmcu%2fLists%2fcortex_mx_stm32%2fProblem%20with%20Timing&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B&currentviews=1913

[ 3953 comments ]   |  [ 0 trackbacks ]   |  permalink  |  related link

<<First <Back | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | Next> Last>>