robustability:
Apologies if this isn't the correct sub-forum.
I am interfacing an ATmega328P (standalone, not on the Arduino board, though I am programming it with the Arduino IDE) with Adafruit's nRF8001 Bluetooth breakout board. I am using Adafruit's code for Arduino, which uses SPI and a few extra pins to setup a UART interface.
Now, everything works perfectly fine at 16 MHz (with external crystal) and at 8 MHz using the "Atmega on a breadboard" code which you can find in the Arduino online tutorials. So next, I recompiled the bootloader code and changed the fuse settings in boards.txt and the makefile so that it would run at 1 MHz. I use "upload using programmer" to load the code which I think overwrites the bootloader anyway, but that's fine... I really just care about the fuse settings being correct and Arduino getting the right timing for the delay() and millis() functions without me having to think about it. When I put together code that does something simple like blink an LED, it works fine at 1 MHz with my new settings. Timing is perfect and everything. But when I try to interface it with the nRF8001 using the same code as before, the code just doesn't execute! Then, if I set CLKPR in my setup( ) function to use a clock divider of 16 instead of 8, making the system clock run at 500 kHz, everything runs fine again.
Any ideas what is going on? Anything I should try? I have a work-around (choose a different clock scaler) but it's frustrating that I don't understand why it isn't working at 1 MHz. I would like to understand.
Leave CKDIV8 unprogrammed (boot at 16 mhz) and leave the bootloader alone, then set the divider in your code. By the way, you don't have to mess with CLKPR... there's a macro in
** **<avr/power.h>** **
called "
** **clock_prescale_set(clock_div_t)** **
" which does it all for you. The dividers are also pre-defined for you (clk_div_1, 2, 4, 8 etc...).
You would call it as such:
#include <avr/power.h> // don't forget this!
clock_prescale_set (clock_div_8); // divide F_CPU by 8
To make your delays and such work right, also do this (obviously the F_CPU must match the frequency the clock divider gives you.
#ifdef F_CPU
#undef F_CPU
#define F_CPU 1000000UL
#endif
Lastly, here's a little "wrapper" I made for that function:
///////////////////////////////////////////////////////////////////////////////
//
// CPU clock speed divider control function for Arduino
// Copyright (c) 2015 Roger A. Krupski <rakrupski@verizon.net>
//
// Last update: 24 August 2015
//
// 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 3 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, see <http://www.gnu.org/licenses/>.
//
///////////////////////////////////////////////////////////////////////////////
#include "wiring_private.h"
uint8_t clockDivide (uint16_t div)
{
uint8_t n = 16;
div = div < 1 ? 1 : div > 256 ? 256 : div; // constrain value to legal
while (! (div & 0x8000)) {
div *= 2;
n--;
}
if (! ((div << 1) & 0x8000)) {
n--;
}
clock_prescale_set ((clock_div_t) n);
return n; // return divider number for other possible uses
}
//// end of clock_divide.cpp ////
With the wrapper, you can put in any number you want and the closest speed will be chosen.