Time to close also this project.
With the help of Roberto we did end up with a PCB, let's put it together.
This article describes some work on the hardware side.
Translate
Showing posts with label msp430. Show all posts
Showing posts with label msp430. Show all posts
Sunday, December 16, 2018
Saturday, December 15, 2018
Sunday, September 23, 2018
tRPOf with Trinket - updated
The main difference from previous ones, is that this project uses a standard Adafruit Trinket as microcontroller instead the MSP430 in order to use "off the shelf" components with less effort of programming and a LiPo charger/USB DC/DC converter..
Saturday, August 11, 2018
Controlling a WS2812B LED
Just some brief notes about LED strips based on the WS2812B (for example this one).
The same LED is also used in the Adafruit circular ring LED (here a datasheet from Adafruit)
The same LED is also used in the Adafruit circular ring LED (here a datasheet from Adafruit)
Sunday, July 15, 2018
MSP430f169 LCD development environment
Until now I always developed code for the Olimex board MSP430F169 LCD using an open source compiler (GNU) and using a parallel port->JTAG adapter to program the board and do some debug.
That requires a computer with parallel port.
The goal of this article is to see if is possible to use an USB->JTAG adapter or using the Spy-by-wire connection.
Saturday, July 14, 2018
MSP430 - Reading a digital encoder
Already exists a lot of documentation about this, but just for fun, I started from the scratch and did some analysis.
I did find very interesting issues about this "common" component.
I did find very interesting issues about this "common" component.
Saturday, May 19, 2018
MSP430 - reading a TSL2561
The TSL2561 is a chipset capable to read IR and visible light intensity and is the chipset used in the iRis project.
This article give some suggestions about how to use this sensor.
This article give some suggestions about how to use this sensor.
Saturday, March 17, 2018
Why sometime ...
... simple things does not work or just make you crazy losing hours and hours if not days ?
Who work in the magical world of the software development, especially embedded or firmware, sometime find himself in weird situation, when something incredibly simple and trivial, simply does not work.
Why ?
Who work in the magical world of the software development, especially embedded or firmware, sometime find himself in weird situation, when something incredibly simple and trivial, simply does not work.
Why ?
Saturday, March 10, 2018
magclock
Years ago I did a very quick project with a MSP430F2013 capable to generate a signal to drive a magnetic clock like the one below
(the video does not represent the actual clock, just an example).
The code, few lines in C, is in the magclock repo on my github account.
The idea is quite simple.
Three coils are controlled by the MSP430 in a sequence, like the brushless hard disk motors, same principle but much much slower.
Basically the system is designed to move a dented wheel one notch every second.
That wheel then controls the other gears of the clock.
The only thing is to have an accurate timing, so better to use a crystal on the MSP430.
This article give some other information about the MSP430 clock capabilities and settings.
(the video does not represent the actual clock, just an example).
The code, few lines in C, is in the magclock repo on my github account.
The idea is quite simple.
Three coils are controlled by the MSP430 in a sequence, like the brushless hard disk motors, same principle but much much slower.
Basically the system is designed to move a dented wheel one notch every second.
That wheel then controls the other gears of the clock.
The only thing is to have an accurate timing, so better to use a crystal on the MSP430.
This article give some other information about the MSP430 clock capabilities and settings.
Friday, March 2, 2018
A personal CI system
In this article I'm describing how to set up and configure a basic CI (Continuos Integration) system that can be used for many things, based on an open source program called Jenkins.
Of course, for my projects to set up a CI to build them is just little bit overshooting, but surely is interesting and fun.
Sunday, January 15, 2017
Energia and MSP430G2553
Recently I had a little bit more deep experience with Energia and the MSP430G2553.
Here some notes about this experience.
Here some notes about this experience.
Saturday, November 14, 2015
Timer for UV box
Ok, here the deal.
The need is to develop a timer, faster, capable to control up to 16 UV fluorescent bulbs.
Up to 2 hours, 1 second precision, display to show the countdown and menu' management, digital encoder for input, pushbuttons/LEDs.
It can be done in thousands ways, but this time I'll try to put it together using Energia and a BIG help from Roberto.
The need is to develop a timer, faster, capable to control up to 16 UV fluorescent bulbs.
Up to 2 hours, 1 second precision, display to show the countdown and menu' management, digital encoder for input, pushbuttons/LEDs.
It can be done in thousands ways, but this time I'll try to put it together using Energia and a BIG help from Roberto.
Wednesday, November 4, 2015
Embedded RPOf
The next thing to do about the RPOf is to embed it in a piggy back board over the Raspberry Pi.
The Raspberry Pi GPIO connector has both the 3.3V and 5V rail available, so to have a more compact system, embedding the RPOf on the "shield" connected to the Raspberry Pi, can helps to reduce the space and number of boards.
The Raspberry Pi GPIO connector has both the 3.3V and 5V rail available, so to have a more compact system, embedding the RPOf on the "shield" connected to the Raspberry Pi, can helps to reduce the space and number of boards.
Friday, October 30, 2015
Working on the iRis project
[To be updated !]
A step-by-step guide to work on git for the iRis project.
If you are new on git and github, read this article first.
The iRis project is on github, so if somebody wants to join it, or just follow the progress, can clone the git repo for iRis.
A step-by-step guide to work on git for the iRis project.
If you are new on git and github, read this article first.
The iRis project is on github, so if somebody wants to join it, or just follow the progress, can clone the git repo for iRis.
Working on RPOf project
Here a step-by-step guide to work on git for the RPOf project.
If you are new on git and github, read this article first.
If you are new on git and github, read this article first.
Tuesday, October 13, 2015
iRis project - an introduction
The purpose of the iRis project is to have a "head" for medical training purpose related to eyes illness.
Basically the idea is to build a "eyes simulator" capable to react to the light like an eye does, in order to simulate different types of illness retina/nerve related.
Basically the idea is to build a "eyes simulator" capable to react to the light like an eye does, in order to simulate different types of illness retina/nerve related.
Tuesday, August 11, 2015
MSP430 - Energia and Grove
I do have few Arduino around.
Like many people I bought some of them because ... well, I don't know, I guess at the time it was the news, to see what it is.
And I didn't like it much.
Saturday, August 8, 2015
MSP430 - I2C library
There are many different library out there to handle I2C with the MSP430.
Some of the libraries are also "official", from TI.
I found a nice and simple C library to handle the I2C with USI is on github and apparently is easy to deploy and use.
This article contains some notes about how to deploy and use the library, closing some missing practical information.
Let's start with ... the hardware.
The library was originally developed and tested on an MSP430g2452.
It surely can work on any MSP430 family member that has a USI, that's was anyway my initial intent.
I tried to use an MSP430f2013 but in the end I opted to buy some MSP430g2452 because the 2013 doesn't have enough memory (only 2K ROM) to handle protocol and the rest of the code needed for a project.
The MSP430g2452 has 8K ROM.
After choosing the microcontroller, the attention was concentrated on the I/O pin to use.
Note ! Initially I'm experiment using a Launchpad.
The library expects to use the USI pins, i.e. the P1.6 for the SCL and the P1.7 for the SDA.
Apparently there is NO need to bother with the I/O ports to inform the MSP430 that the 2 pins are dedicated to the USI in I2C mode.
Is enough to program the USI control register to do that, and that is taken care in the i2c_init function provided by the library.
Important !!! The P1.6 on the Launchpad is connected to the green LED !
Remove the jumper on that LED in order to have something working !
The library presumably is written for IAR or other commercial system.
In order to compile it with Mspgcc few modifications are necessary.
I also fixed a bug that was preventing the library to read more than 8 bit at a time.
In the usi_i2c.c file, in the interrupt function Usi_txrx change the highlighted line :
..................................................................
..................................................................
case I2C_RECEIVED_DATA: // received data, send ACK/NACK
*i2c_receive_buffer = USISRL;
i2c_receive_buffer++;
USICTL0 |= USIOE; // SDA = output
if(i2c_sequence_length > 1) {
// If this is not the last byte
USISRL = 0x00; // ACK
..................................................................
..................................................................
The library has only three "public" functions and act as Master.
Let see how to use it.
The first public function is called i2c_init and like the name imply, is used to initialize the USI and set up the MSP430 to use it.
It must be called once, preferably after other basic I/O initializations happens.
After that, the "system" should be able to send out I2C messages.
Example:
i2c_init(USIDIV_5, USISSEL_2);
The first parameter determine the division applied to the input clock.
USIDEV_0 divide by 1, USIDEV_1 divide by 2, USIDEV_2 divide by 4 and so on (see MSP430 Family user guide - USICKCTL register).
The second parameter determine the source of the clock (see MSP430 Family user guide - USICKCTL register).
In the example above the source for the clock is the SMCLK divided by 32.
This function returns TRUE (1) or FALSE (0) to indicate if a transaction is running.
The I2C messages are sent via interrupt so it is possible that the main program is ready to send another sequence when the system is still handling the previous sequence.
So before to perform any request, better to see if the system is ready to accept it.
Example:
if(i2c_done())
i2c_send_sequence((uint16_t *)seq1, 2, (uint8_t *)recseq, 0);
or
while(!i2c_done());
Strongly suggested to use it to prevent to start a sequence when another one is still running.
Simply put, this function can send and receive information via I2C using a "sequence".
The sequence is a series of word and commands.
i2c_usi.h defines two commands :
The sequences to send depends strictly to a specific component so there is no a generic suggestion if not to carefully read the datasheet of the component.
Some of the libraries are also "official", from TI.
I found a nice and simple C library to handle the I2C with USI is on github and apparently is easy to deploy and use.
This article contains some notes about how to deploy and use the library, closing some missing practical information.
Let's start with ... the hardware.
Hardware
The library was originally developed and tested on an MSP430g2452.
It surely can work on any MSP430 family member that has a USI, that's was anyway my initial intent.
I tried to use an MSP430f2013 but in the end I opted to buy some MSP430g2452 because the 2013 doesn't have enough memory (only 2K ROM) to handle protocol and the rest of the code needed for a project.
The MSP430g2452 has 8K ROM.
After choosing the microcontroller, the attention was concentrated on the I/O pin to use.
Note ! Initially I'm experiment using a Launchpad.
The library expects to use the USI pins, i.e. the P1.6 for the SCL and the P1.7 for the SDA.
Apparently there is NO need to bother with the I/O ports to inform the MSP430 that the 2 pins are dedicated to the USI in I2C mode.
Is enough to program the USI control register to do that, and that is taken care in the i2c_init function provided by the library.
Important !!! The P1.6 on the Launchpad is connected to the green LED !
Remove the jumper on that LED in order to have something working !
Software
Compile it
The library presumably is written for IAR or other commercial system.
In order to compile it with Mspgcc few modifications are necessary.
- Remove the specific include of the msp430g2452 header from usi_i2c.c
- Add the generic include of msp430 in the usi_i2c.h
- Remove the include of the stdint.h header from usi_i2c.c and move in the usi_i2c.h
- Change the interrupt declaration, from:
#pragma vector = USI_VECTOR
__interrupt void USI_TXRX(void)
{
switch(__even_in_range(i2c_state,12))
to
__attribute__((__interrupt__(USI_VECTOR)))
void Usi_txrx (void){ switch(__even_in_range(i2c_state,12)) - Move the inline function i2c_done() from the header file (usi_i2c.h) into the module (usi_i2c.c) and leave a function prototype for that function in the usi_i2c.h header file
With these modifications I was able to compile the library using mspgcc.
I also fixed a bug that was preventing the library to read more than 8 bit at a time.
In the usi_i2c.c file, in the interrupt function Usi_txrx change the highlighted line :
..................................................................
..................................................................
case I2C_RECEIVED_DATA: // received data, send ACK/NACK
*i2c_receive_buffer = USISRL;
i2c_receive_buffer++;
USICTL0 |= USIOE; // SDA = output
if(i2c_sequence_length > 1) {
// If this is not the last byte
USISRL = 0x00; // ACK
..................................................................
..................................................................
with
..................................................................
..................................................................
case I2C_RECEIVED_DATA: // received data, send ACK/NACK
*i2c_receive_buffer = USISRL;
i2c_receive_buffer++;
USICTL0 |= USIOE; // SDA = output
if(i2c_sequence_length > 0) { // TheFwGuy MOD !!!
// If this is not the last byte
USISRL = 0x00; // ACK
..................................................................
..................................................................
..................................................................
case I2C_RECEIVED_DATA: // received data, send ACK/NACK
*i2c_receive_buffer = USISRL;
i2c_receive_buffer++;
USICTL0 |= USIOE; // SDA = output
if(i2c_sequence_length > 0) { // TheFwGuy MOD !!!
// If this is not the last byte
USISRL = 0x00; // ACK
..................................................................
..................................................................
Use it
The library has only three "public" functions and act as Master.
Let see how to use it.
i2c_init
The first public function is called i2c_init and like the name imply, is used to initialize the USI and set up the MSP430 to use it.
It must be called once, preferably after other basic I/O initializations happens.
After that, the "system" should be able to send out I2C messages.
Example:
i2c_init(USIDIV_5, USISSEL_2);
The first parameter determine the division applied to the input clock.
USIDEV_0 divide by 1, USIDEV_1 divide by 2, USIDEV_2 divide by 4 and so on (see MSP430 Family user guide - USICKCTL register).
The second parameter determine the source of the clock (see MSP430 Family user guide - USICKCTL register).
In the example above the source for the clock is the SMCLK divided by 32.
i2c_done
This function returns TRUE (1) or FALSE (0) to indicate if a transaction is running.
The I2C messages are sent via interrupt so it is possible that the main program is ready to send another sequence when the system is still handling the previous sequence.
So before to perform any request, better to see if the system is ready to accept it.
Example:
if(i2c_done())
i2c_send_sequence((uint16_t *)seq1, 2, (uint8_t *)recseq, 0);
or
while(!i2c_done());
Strongly suggested to use it to prevent to start a sequence when another one is still running.
i2c_send_sequence
This is the main function and the most complex to handle.Simply put, this function can send and receive information via I2C using a "sequence".
The sequence is a series of word and commands.
i2c_usi.h defines two commands :
- I2C_RESTART
- I2C_READ
The function has these inputs:
- sequence
sequence is a pointer to an array containing the I2C operation sequence that should be performed.
It can include any number of writes, restarts and reads.
The sequence is composed of uint16_t, not uint8_t elements.
This is because the need to support out-of-band signalling of I2C_RESTART and I2C_READ operations, while still passing through 8-bit data.
The sequence uses the Bus Pirate I2C convention.
The address must be prepared manually, adding the R/W bit.
The address is prepared shifting the 7-bit I2C address to the left and add the R/W bit (0 to write, 1 to read).
The examples above communicate with a device whose I2C address is 0x1c, which shifted left gives 0x38.
For reads we use 0x39, which is (0x1c<<1)|1.
So for example, to write at the address 0x39, the sequence would be:
- 0x39 << 1 = 0x72
And to read from the address 0x39:- (0x39 << 1) | 1 = 0x73
- sequence length
sequence_length is the number of sequence elements (not bytes).
Sequences of arbitrary (well, 32-bit) length are supported. - received data
received_data should point to a buffer that can hold as many bytes as there are I2C_READ operations in the sequence.
If there are no reads, 0 can be passed, as this parameter will not be used. - wake up sr bits
Used if you want to use the MSP430 in low power mode.
Building sequences
The sequences to send depends strictly to a specific component so there is no a generic suggestion if not to carefully read the datasheet of the component.
Sunday, April 19, 2015
MSP430 - generating a PWM signal
This article discuss some basic ways to generate a PWM signal using a MSP430.
A PWM signal is a digital signal with fixed frequency but varying duty cycle.
If the duty cycle of the PWM signal is varied with time, and the PWM signal is filtered, the output of the filter will be an analog signal.
There are mostly 3 ways to generate a PWM signal using a MSP430 :
Theory of operations
A PWM signal is a digital signal with fixed frequency but varying duty cycle.
If the duty cycle of the PWM signal is varied with time, and the PWM signal is filtered, the output of the filter will be an analog signal.
There are mostly 3 ways to generate a PWM signal using a MSP430 :
- loop
- timer
- interrupt
Loop
The easiest way to generate a PWM signal is to create an infinite loop and inside the loop, set a I/O pin ON or OFF, using a counter to determine when to change the ON vs. OFF time, comparing it to a "dutycycle" value. Also in the loop must be present a delay to determine the frequency of the signal.
The pro is obvious, is really easy to generate a PWM signal in this way.
But there are big cons with this method.
Let see some of them:
Two MSP430 subsystems are involved in generating a PWM signal with the timer, the clock subsystem and the timer subsystem.
The output pin of the PWM signal, is directly connected to the timer.
Once programmed the timer, the generation of the PWM signal doesn't require any additional software.
In this way, a timer is still involved, but instead to generate the PWM signal, it generate interrupts.
Any time the interrupt is fired, a piece of software provide to change the state of an I/O pin depending some counter values compared with a threshold, generating in this way the PWM signal.
The frequency of the signal is determined by the timer setting and the precision is depending by the number of "steps" of the counter.
For example, if we want a 100 Hz signal, we need to set up an interrupt timing "at least" set to fire every 1/(100 Hz * 2) i.e. 0.005 seconds.
It means that every 0.005 seconds we have an interrupt and change the state of the output, obtaining a square wave of 100 Hz.
But we want to control the duty cycle, and so we need to have a smaller interrupt time.
Let say we want to divide our 100 Hz in 10 "steps", so we need to set the timer to fire every 1/(100 Hz/10) = 0.001 seconds or 1 ms.
Every ms we have an interrupt and then we decide if having the output ON or OFF.
Our period is so divided in 10 1 ms steps, i.e. 0.001 * 10 = 0.1 sec. that converted is 100 Hz.
But only 10 steps is not good, so better to split the time more, at least 50 or 100.
Of course we have some limits depending the input clock and how long the interrupt function requires to operate.
So we have to play with the clock in order to have the micro go faster and really optimize the interrupt function.
The interrupt function must be executed in a time much shorter than 1 ms, and we need to decide if the output is high or low depending a counter value in that timeframe.
Here a flow chart to better explain the basics.
On the left a flow of the main code.
It simply initialize the system and enter in an infinite loop. Eventually is possible to have code to perform settings/change of the parameters in the loop.
On the right the flow of the timer interrupt.
Every time the interrupt is fired, it uses a counter compared with a threshold to determine if turn the signal ON or OFF and then update the counter restarting the timer.
To measure exactly how long on average the function last, a debug signal is used.
The code turn this debug signal ON just after started the interrupt and OFF just before to exit.
With an oscilloscope is then possible to measure how long the signal remain ON. That more or less would be the time used by the interrupt function.
Here a couple of pictures from my oscilloscope during some tests.
The pro is obvious, is really easy to generate a PWM signal in this way.
But there are big cons with this method.
Let see some of them:
- all the resources of the processor are devoted to generate the signal
- is extremely difficult to calculate a specific timing
- any extra operation added in the loop go to alter the frequency of the generated signal
- if interrupts are used the result signal is extremely instable
So the loop is not really something to consider for real use.
Timer
The second way to generate a PWM signal is to use a timer.
The MSP430 timer is capable to generate a PWM signal, it means that is possible to program a MSP430 timer specifically for the purpose to generate a PWM signal.
Because the signal in the end is generated by a piece of hardware, the result is extremely stable and precise.
Pro:
- very stable PWM signal
- extremely precise timing is possible
Cons:
- the timer is devoted only to the PWM signal generation since the I/O pin is connected to it
- only 1 PWM signal per timer is available
- setting up the timer can be complicated
Interrupt
The third alternative is to soft-generate the PWM, like in the loop solution, but using a timer interrupt instead a deal loop.
A generic timer interrupt is generated and every time the interrupt is fired, a function handle one or more I/O pins to generate the PWM signal.
Pro:
- stable PWM signal
- precise timing (but less than the full timer solution)
- possibility to have more than one PWM signals
- possibility to use the timer resource for other purposes
- easy to calculate the time
Cons:
- limited timing range
PWM generated by a timer
The output pin of the PWM signal, is directly connected to the timer.
Once programmed the timer, the generation of the PWM signal doesn't require any additional software.
Clock
The timer needs to be "fed" with a clock and there are different choices, depending the time required and the precision needed.PWM using a generic time interrupt
In this way, a timer is still involved, but instead to generate the PWM signal, it generate interrupts.
Any time the interrupt is fired, a piece of software provide to change the state of an I/O pin depending some counter values compared with a threshold, generating in this way the PWM signal.
The frequency of the signal is determined by the timer setting and the precision is depending by the number of "steps" of the counter.
For example, if we want a 100 Hz signal, we need to set up an interrupt timing "at least" set to fire every 1/(100 Hz * 2) i.e. 0.005 seconds.
It means that every 0.005 seconds we have an interrupt and change the state of the output, obtaining a square wave of 100 Hz.
But we want to control the duty cycle, and so we need to have a smaller interrupt time.
Let say we want to divide our 100 Hz in 10 "steps", so we need to set the timer to fire every 1/(100 Hz/10) = 0.001 seconds or 1 ms.
Every ms we have an interrupt and then we decide if having the output ON or OFF.
Our period is so divided in 10 1 ms steps, i.e. 0.001 * 10 = 0.1 sec. that converted is 100 Hz.
But only 10 steps is not good, so better to split the time more, at least 50 or 100.
Of course we have some limits depending the input clock and how long the interrupt function requires to operate.
So we have to play with the clock in order to have the micro go faster and really optimize the interrupt function.
Here a flow chart to better explain the basics.
On the left a flow of the main code.
It simply initialize the system and enter in an infinite loop. Eventually is possible to have code to perform settings/change of the parameters in the loop.
On the right the flow of the timer interrupt.
Every time the interrupt is fired, it uses a counter compared with a threshold to determine if turn the signal ON or OFF and then update the counter restarting the timer.
To measure exactly how long on average the function last, a debug signal is used.
The code turn this debug signal ON just after started the interrupt and OFF just before to exit.
With an oscilloscope is then possible to measure how long the signal remain ON. That more or less would be the time used by the interrupt function.
Here a couple of pictures from my oscilloscope during some tests.
![]() |
| Debug signal in the timer interrupt - DCO set for 16 Mhz selection. The irregular wave indicates different execution timing, approx 3.5 us average execution time |
![]() |
| PWM signal generated, 10 steps, approx 10Khz frequency - DCO set for 16 Mhz selection |
Saturday, April 11, 2015
MSP430 - setting up the clock
All the microcontrollers needs a clock signal to work.
The MSP430 family is not an exception and actually there are many choices when we talk about the clock.
It is important ALWAYS to have handy the LATEST MSP430 family document and the specific chipset documentation, for example the MSP430F20x2 family (an entry level).
Some schematics/pictures shown here are copied from the MSP430 family document.
Let see the MSP430 clock system
The first thing that come up from the picture above, is that we have three different clock signal generated:
The most important signal generated is the MCLK, the Main System Clock.
As the name imply, this is the clock signal used by the core of the MSP430 chipset, the CPU and basic signals (memory bus/I/O bus/ecc.).
The SMCLK signal is the Sub system clock.
It is normally connected to the peripherals, like the Timer, Watchdog and every peripheral that can require a clock.
The ACLK is an Auxiliary clock.
Sometime it can be necessary to have peripherals using different clocks. For example a UART can require a special timing if compared with the other peripherals or a specific timer needs a low and precise timing.
The Auxiliary clock cannot use the DCO oscillator. It can use only the crystal oscillator.
When the chip is turned ON, i.e. after a hard reset, the clock subsystem is set to generate an approx. 800 kHz signal on the MCLK and SMCLK pin.
This allows the chipset to be able to start to execute instructions. A default clock mechanism must be present otherwise it would be impossible to "program the clock subsystem" if no instructions can be executed.
By default, the source for the SMCLK is the same of the MCLK, the DCO generator.
There are four possible sources for the clock:
This clock runs around 12 kHz and it can be used when the chipset is put in low power mode.
It is reasonably precise.
If the precision of the clock is not an issue, there is no need to worry about using calibrated values for the DCO.
Because the tolerance of the components, each MSP430 needs a different set of resistor values to set up the clock for specific frequencies.
It would be a very time consuming task to use external resistors, figuring out what is the correct value for a specific frequency, but fortunately TI though about that.
Every MSP430 chip has a table containing the calibrated (values) for the internal resistor array.
Is enough to read the table and acquire the value for the setting needed.
It is also possible to re-write the table for specific needs, as described in this article.
To determine what setting is needed for specific frequency, requires to study the specific chipset datasheet.
For example, for the MSP430f2012 the datasheet has a table indicating what frequency, with quite a tolerance, correspond to different settings of some specific registers.
Looking at the table, the frequencies generated by the DCO have a quite big tolerance.
This why it could be necessary to re-calibrate the DCO values if a more precise frequency is needed.
As the name imply, these circuits allows to generate a frequency dependent by a crystal.
They are less flexible than the DCO but they can be very precise and stable.
At least one crystal oscillator is present on every MSP430 chipset.
Here some examples about how is possible to set up the MSP430 clock.
The examples are using the MSP430F2012.
The default setting is for a middle/low frequency, around 800kHz (800kHz to 1.5 MHz), but the DCO can reach the 16 MHz in some chipsets.
Unless specific needs, is not a good idea to set the DCO for the maximum frequency.
Mainly because more fast the chip run, more current use and more heat is generated, but also because higher is the generated frequency, lower is the stability and precision.
Is a good idea to use a an external crystal if high speed and precision is required.
To determine what frequency to use it is mandatory to read the data sheet of the specific component, because each device has an internal table with some values to use for the DCO.
Said so, a typical DCO setting for about 8 Mhz is this one.
DCOCTL = 0x60;
BCSCTL1 = 0xB3;
BCSCTL2 = 0x00;
BCSCTL3 = 0x0C;
The DCOCTL (Digitally Controlled Oscillator Control register) after a reset is set for:
The BCSCTL1 register (Basic Clock Control Register 1) after the reset has the value of 84 hex (1000 0100), i.e. :
When is necessary to count time for a clock, timer or watch, normally it is used a crystal of 32768-Hz (3.2768 kHz) because is easy to divide this frequency to obtain 1 second.
Of course we don't want the main clock system signal be so slow, this is the typical setting for the ACLK signal.
Let see what we need to be aware and what to do to have the basic clock set on that.
First of all some hardware is required.
Then the software.
We need to set up some chipset registers in order to have the clock up and running.
BCSCTL1 |= DIVA_3; /* ACLK/8 */
BCSCTL3 |= XCAP_3; /* 12.5pF cap */
Let see some details.
The BCSCTL1 register (Basic Clock Control Register 1) after the reset has the value of 84 hex (1000 0100), i.e. :
The MSP430 family is not an exception and actually there are many choices when we talk about the clock.
It is important ALWAYS to have handy the LATEST MSP430 family document and the specific chipset documentation, for example the MSP430F20x2 family (an entry level).
Some schematics/pictures shown here are copied from the MSP430 family document.
Let see the MSP430 clock system
The first thing that come up from the picture above, is that we have three different clock signal generated:
- MCLK
- SMCLK
- ACLK
MCLK
The most important signal generated is the MCLK, the Main System Clock.
As the name imply, this is the clock signal used by the core of the MSP430 chipset, the CPU and basic signals (memory bus/I/O bus/ecc.).
SMCLK
The SMCLK signal is the Sub system clock.
It is normally connected to the peripherals, like the Timer, Watchdog and every peripheral that can require a clock.
ACLK
The ACLK is an Auxiliary clock.
Sometime it can be necessary to have peripherals using different clocks. For example a UART can require a special timing if compared with the other peripherals or a specific timer needs a low and precise timing.
The Auxiliary clock cannot use the DCO oscillator. It can use only the crystal oscillator.
Clock sources
When the chip is turned ON, i.e. after a hard reset, the clock subsystem is set to generate an approx. 800 kHz signal on the MCLK and SMCLK pin.
This allows the chipset to be able to start to execute instructions. A default clock mechanism must be present otherwise it would be impossible to "program the clock subsystem" if no instructions can be executed.
By default, the source for the SMCLK is the same of the MCLK, the DCO generator.
There are four possible sources for the clock:
- Very low frequency clock
- DCO
- Crystal oscillator 1
- Crystal oscillator 2
Some chipset could have only one crystal oscillator, so is important to know what chipset you are using.
Very low frequency clock
This clock runs around 12 kHz and it can be used when the chipset is put in low power mode.
It is reasonably precise.
DCO
The DCO (Digitally Controlled Oscillator) is the default source of clock for the MCLK and SMCLK.
As the name imply, it is possible to set up this oscillator simply writing the setting in some registers.
Different frequencies can be generated simply changing some register settings.
There are Pro and Cons using the DCO.
There are Pro and Cons using the DCO.
Pro:
- flexible frequency generator
- doesn't require ANY external hardware
- fast
Cons:
- less stable and precise than crystal
- it require a tuning procedure
DCO calibrated values
The DCO uses resistors, external or internal, to set up a specific frequency.If the precision of the clock is not an issue, there is no need to worry about using calibrated values for the DCO.
Because the tolerance of the components, each MSP430 needs a different set of resistor values to set up the clock for specific frequencies.
It would be a very time consuming task to use external resistors, figuring out what is the correct value for a specific frequency, but fortunately TI though about that.
Every MSP430 chip has a table containing the calibrated (values) for the internal resistor array.
Is enough to read the table and acquire the value for the setting needed.
It is also possible to re-write the table for specific needs, as described in this article.
To determine what setting is needed for specific frequency, requires to study the specific chipset datasheet.
For example, for the MSP430f2012 the datasheet has a table indicating what frequency, with quite a tolerance, correspond to different settings of some specific registers.
Looking at the table, the frequencies generated by the DCO have a quite big tolerance.
This why it could be necessary to re-calibrate the DCO values if a more precise frequency is needed.
Crystal Oscillators
As the name imply, these circuits allows to generate a frequency dependent by a crystal.
They are less flexible than the DCO but they can be very precise and stable.
At least one crystal oscillator is present on every MSP430 chipset.
Programming examples
Here some examples about how is possible to set up the MSP430 clock.
The examples are using the MSP430F2012.
Select DCO for ~8 MHz
After a reset, the main source for the clock, especially MCLK, is the DCO.The default setting is for a middle/low frequency, around 800kHz (800kHz to 1.5 MHz), but the DCO can reach the 16 MHz in some chipsets.
Unless specific needs, is not a good idea to set the DCO for the maximum frequency.
Mainly because more fast the chip run, more current use and more heat is generated, but also because higher is the generated frequency, lower is the stability and precision.
Is a good idea to use a an external crystal if high speed and precision is required.
To determine what frequency to use it is mandatory to read the data sheet of the specific component, because each device has an internal table with some values to use for the DCO.
Said so, a typical DCO setting for about 8 Mhz is this one.
DCOCTL = 0x60;
BCSCTL1 = 0xB3;
BCSCTL2 = 0x00;
BCSCTL3 = 0x0C;
- Frequency select middle range (value from 0 to 7, set to 3)
- Modulator section = 0
The setting to 0x60, according to the table above, set the frequency between 6 MHz to 9MHz.
The BCSCTL1 register (Basic Clock Control Register 1) after the reset has the value of 84 hex (1000 0100), i.e. :
- Crystal Oscillator 2 disabled (OFF)
- Crystal low frequency mode
- ACLK signal divided by 1 (i.e. no division)
- DCO Resistor select = 4 (nominal frequency for DCO)
After the selection (BCSCTL1 = 0xB3 - 1011 0011):
- Crystal Oscillator 2 disabled (OFF)
- Crystal low frequency mode
- ACLK signal divided by 8
- DCO Resistor select = 3
The BCSCTL2 after the reset is set to zero and no change is made, meaning:
- source for MCLK = DCO
- no divider for MCLK (divider = 1)
- source for SMCLK = DCO
- no divider for SMCLK (divider = 1)
- use internal resistor for frequency selection
The BCSCTL3 after the reset is set to zero:
- Crystal oscillator 2 range 0 to 4 MHz (not used anyway)
- 3.2768 kHz crystal selected (not used anyway)
- 6 pf capacitor selected for crystal (not used anyway)
After the writing (0x0C - 0000 0011)
- Crystal oscillator 2 range 0 to 4 MHz (not used anyway)
- 3.2768 kHz crystal selected (not used anyway)
- 1 pf capacitor selected for crystal (not used anyway)
Note that the first two bits are only reading.
Classic watch generator
When is necessary to count time for a clock, timer or watch, normally it is used a crystal of 32768-Hz (3.2768 kHz) because is easy to divide this frequency to obtain 1 second.
Of course we don't want the main clock system signal be so slow, this is the typical setting for the ACLK signal.
Let see what we need to be aware and what to do to have the basic clock set on that.
First of all some hardware is required.
- connect the crystal
A 32768-Hz crystal need to be connected to the chipset (pin XIN and XOUT)
Usually this require also some capacitors other the crystal, but the chipset has them inside - setting the pins
Because the crystal is physically connected to some chip pins, we need to program the I/O subsystem accordingly.
i.e. we need to program the pins connected to the crystal to be rerouted to the clock subsystem.
By default, i.e. after a reset, assuming we are using an MSP430F2012, the XIN and XOUT pins are enabled, i.e. by default these pins are used for the crystal oscillator 1.
So no specific programming on the I/O subsystem is necessary to use a crystal.
Then the software.
We need to set up some chipset registers in order to have the clock up and running.
BCSCTL1 |= DIVA_3; /* ACLK/8 */
BCSCTL3 |= XCAP_3; /* 12.5pF cap */
Let see some details.
The BCSCTL1 register (Basic Clock Control Register 1) after the reset has the value of 84 hex (1000 0100), i.e. :
- Crystal Oscillator 2 disabled (OFF)
- Crystal low frequency mode
- ACLK signal divided by 1 (i.e. no division)
- Resistor select = 4 (nominal frequency for DCO)
So the register controls different parts of the clock subsystem.
The line BCSCTL1 |= DIVA_3; set only the DIVA bits, changing the original value from 0 to 3, setting the divisor of the ACLK signal to 8. i.e. the generated frequency of the ACLK will be divided by 8.
The BCSCTL3 register after the reset has the value of 00x (the first two bits are to indicate some fault condition so they can have random setting after a reset).
i.e.:
- Range for Crystal oscillator 2 : 0 to 1 MHz crystal
- 3.2768 kHz crystal on oscillator 1
- 1 pf internal capacitor
The bit 2 and 3 select an internal capacitor to be used with an external crystal.
In our example, we use a 12.5 pF internal capacitor so the selection is 3 (11) for these bits, forced with the line : BCSCTL3 |= XCAP_3;
This is enough to have the ACLK signal generated.
The ACLK signal will have a 32768 Hz / 8 = 4096 Hz.
The ACLK signal will have a 32768 Hz / 8 = 4096 Hz.
This value is easily used by the timer in order to generate precise and low periods.
Subscribe to:
Posts (Atom)










