Timer 带arduino的attiny85位bang uart
我曾尝试为ATTiny85实现仅发送uart,并使用arduino micro接收位。(没有帮助,因为这与我的情况完全不同) 我的目的是能够通过attiny85->arduino->控制台打印,这样我就可以调试attiny85,因为我没有示波器可用 attiny85保险丝为:“efuse:w:0xff:m-U hfuse:w:0xdf:m-U lfuse:w:0xf1:m”。16MHz F_CPU arduino似乎也有16MHz的F_CPU 与上述问题类似,attiny85通过定时器0 ISR一次发送一位:Timer 带arduino的attiny85位bang uart,timer,arduino,uart,attiny,Timer,Arduino,Uart,Attiny,我曾尝试为ATTiny85实现仅发送uart,并使用arduino micro接收位。(没有帮助,因为这与我的情况完全不同) 我的目的是能够通过attiny85->arduino->控制台打印,这样我就可以调试attiny85,因为我没有示波器可用 attiny85保险丝为:“efuse:w:0xff:m-U hfuse:w:0xdf:m-U lfuse:w:0xf1:m”。16MHz F_CPU arduino似乎也有16MHz的F_CPU 与上述问题类似,attiny85通过定时器0 ISR
#ifndef F_CPU
#define F_CPU 16000000UL // 16 MHz
#endif
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#define TX_PIN PB0
volatile uint16_t tx_shift_reg = 0;
ISR(TIMER0_COMPA_vect) {
uint16_t local_tx_shift_reg = tx_shift_reg;
if( local_tx_shift_reg & 0x01 ) {
PORTB |= _BV(TX_PIN);
} else {
PORTB &= ~_BV(TX_PIN);
}
local_tx_shift_reg >>= 1;
if(!local_tx_shift_reg) {
// Stop timer0.
GTCCR |= (1<<TSM) | (1<<PSR0);
}
tx_shift_reg = local_tx_shift_reg;
}
void UART_tx(char byte) {
uint16_t local_tx_shift_reg = tx_shift_reg;
local_tx_shift_reg = (0b1<<9) | ((uint16_t)byte<<1);
tx_shift_reg = local_tx_shift_reg;
TCNT0 = 0;
TCCR0B |= (1<<CS02)|(1<<CS00); // 1024 prescaler
GTCCR &= ~(1<<TSM);
}
void UART_tx_char(char c) {
UART_tx( c );
// wait until transmission is finished
while(tx_shift_reg);
}
void UART_init() {
cli()
// set TX pins as output
DDRB |= (1<<TX_PIN);
PORTB |= (1<<TX_PIN);
// set timer0 to CTC mode, keep it halted.
TCCR0A |= (1<<WGM01);
TCCR0B = 0;
// enable interrupt
TIMSK |= (1<<OCIE0A);
OCR0A = 128;
OCR0B = 128;
TCNT0 = 0;
GTCCR |= (1<<TSM);
sei();
}
void main(void)
{
UART_init();
while(1) {
for(char c = 1; c < 128; ++c) {
UART_tx_char(c);
_delay_ms(100);
}
}
}
\ifndef F\u CPU
#定义F_CPU 1600000UL//16 MHz
#恩迪夫
#包括
#包括
#包括
#定义TX_引脚PB0
易失性uint16\u t tx\u shift\u reg=0;
行业特殊报告员(计时器公司){
uint16\u t local\u tx\u shift\u reg=tx\u shift\u reg;
if(本地发送移位寄存器&0x01){
端口B |=_BV(TX|U引脚);
}否则{
端口B&=~\u BV(TX\u引脚);
}
本地_-tx_-shift_-reg>>=1;
如果(!本地发送移位寄存器){
//停止计时器0。
GTCCR |=(1我最近遇到了另一端串行通信作为垃圾输出的问题。在我的例子中,ATtiny85使用USB-to-TTL UART转换器向我的笔记本电脑发送位,该转换器在其他情况下工作得很好,但我只是在Arduino IDE串行监视器中收到垃圾
我发现了一个关于校准OSCCAL
的方法
在我的相关课程中,我有点喜欢,但我测试了我应该使用以下代码校准OSCCAL
的理论:
#include <SoftwareSerial.h>
SoftwareSerial comm(-1, 0);
static const int anchor = 128;
void
print_osccal(int v) {
comm.println(F("********************************"));
comm.print(F("OSCCAL = "));
comm.println(v);
comm.println(F("********************************"));
}
void
setup() {
delay(5000);
comm.begin(300);
OSCCAL = anchor;
print_osccal(anchor);
delay(5000);
}
void
loop() {
int x;
for (int i = 1; i < 128; ++i) {
x = anchor + i;
OSCCAL = x;
print_osccal(x);
delay(1000);
x = anchor - i;
OSCCAL = x;
print_osccal(x);
delay(1000);
}
}
#包括
软件串行通信(-1,0);
静态常数int-anchor=128;
无效的
打印光盘(int v){
comm.println(F)(“*************************************”);
通讯打印(F(“OSCCAL=”);
通讯打印(v);
comm.println(F)(“*************************************”);
}
无效的
设置(){
延迟(5000);
通信开始(300);
OSCCAL=锚;
打印光盘(锚);
延迟(5000);
}
无效的
循环(){
int x;
对于(int i=1;i<128;++i){
x=锚+i;
OSCCAL=x;
打印光盘(x);
延迟(1000);
x=锚-i;
OSCCAL=x;
打印光盘(x);
延迟(1000);
}
}
这是一个启示,在串行监视器中看到垃圾突然转变为格式良好的消息(当然,返回垃圾,因为搜索是一个无限循环)
现在,ATtiny85的内部振荡器只能支持1MHz和8MHz。据我所知,OSCCAL
的存在是因为该内部振荡器1)不太准确,2)对温度非常敏感
如果ATtiny85设置为16MHz运行,它需要一个可靠的外部振荡器,不需要再摆弄OSCCAL
可能会有帮助。但是,在我的情况下,它确实允许我发现使SoftwareSerial
在8MHz下运行的值,以及从300
到38400
的波特率范围
这使我能够为位触发UART获得正确的值,以与SoftwareSerial
不支持的1MHz时钟一起工作,非常有趣的是,16MHz时钟的ATtiny85可能不可靠。这可能解释了为什么在较高的串行速度下时钟会很快地去同步。谢谢!
#include <SoftwareSerial.h>
SoftwareSerial comm(-1, 0);
static const int anchor = 128;
void
print_osccal(int v) {
comm.println(F("********************************"));
comm.print(F("OSCCAL = "));
comm.println(v);
comm.println(F("********************************"));
}
void
setup() {
delay(5000);
comm.begin(300);
OSCCAL = anchor;
print_osccal(anchor);
delay(5000);
}
void
loop() {
int x;
for (int i = 1; i < 128; ++i) {
x = anchor + i;
OSCCAL = x;
print_osccal(x);
delay(1000);
x = anchor - i;
OSCCAL = x;
print_osccal(x);
delay(1000);
}
}