Witam wszystkich, mam problem z obsługą przetwornika MAX1301 przez Atmege 32. Mianowicie przetwornik ten posiada 3 tryby pracy. W dwóch sygnał zegarowy podawany jest z zewnątrz, dokładniej przez linię SCLK interfejsu SPI. W trzecim trybie sygnał zegarowy podawany jest na przetwornik tylko podczas przesyłania do niego bitu startowego i odczytu zmierzonych wartości, natomiast podczas samego próbkowania uruchamia się wewnętrzny zegar. I właśnie z tym trybem mam problem. Chciałbym żeby przetwornik pracował w trybie z wewnętrznym zegarem: Internal Clock-Mode, żebym mógł w trakcie próbkowania przejść z uC w stan uśpienia. Udało mi się uruchomić przetwornik w trybie zewnętrznym: External Clock-Mode i wyświetlić zmierzone wartości na LCD. Dlatego zakładam, że problem nie leży ani po stronie obsługi SPI czy LCD, tylko przerwań zewnętrznych. W trybie wewnętrznym po skończonej konwersji wyprowadzenie SSTRB przechodzi w stan wysoki i właśnie ten sygnał chce wykorzystać do inicjacji przerwań, podłączając je na wejście INT0. Z racji tego, że czas narastania/opadania SSTRB wynosi tylko 10ns uznałem że nie ma sensu uruchamiać przerwania na zbocze narastające czy też podłączać tego sygnału na INT2. Wykrywanie przerwania początkowo robiłem poprzez "Any logical change on INT0 generates an interrupt request". Następnie poprzez tranzystor BD237 zwierałem INT0 do masy (tj. SSTRB podłaczone z bazą, INT0 na colektor, a emiter z masą). I w tym przypadku wykrywanie przerwania ani na poziom niski ani na zmianę sygnału nic nie dawało. Nie mam pojęcia co robię nie tak, dlatego byłbym wdzięczy za pomoc.
Zamieszczam link do dokumentacji MAX1301 Link
Przebiegi dla trybu External Clock-mode conversion, który udało mi się uruchomić:
Przebiegi dla trybu Internal Clock-Mode conversion, który chcę uruchomić:
herddef.h
spi.h
spi.c
przerwania.h
przerwania.c
main.c
Zamieszczam link do dokumentacji MAX1301 Link
Przebiegi dla trybu External Clock-mode conversion, który udało mi się uruchomić:
Przebiegi dla trybu Internal Clock-Mode conversion, który chcę uruchomić:
herddef.h
#ifndef HARDDEF_H_INCLUDED
#define KHARDDEF_H_INCLUDED
////////////////////==LCD.H==//////////////////
#define lcd_ddr DDRA
#define lcd_port PORTA
#define lcd_pin PINA
#define lcd_rs 0 //rozróżnienie dane - 1 / instrukcja - 0
#define lcd_rw 1 //kierunek transmisji odczyt - 1 / zapis - 0
#define lcd_e 2 //sygnał potwierdzający
#define lcd_db4 3
#define lcd_db5 4
#define lcd_db6 5
#define lcd_db7 6
////////////////////==SPI==//////////////////
#define SPI_DDR DDRB
#define SPI_PORT PORTB
#define SPI_PIN PINB
#define SCK 7
#define MISO 6
#define MOSI 5
#define AC 4
#define AC_SSTRB 2
#define AC_OFF SPI_PORT |= _BV(AC)
#define AC_ON SPI_PORT &=~_BV(AC)
#endif
spi.h
#ifndef SPI_H_INCLUDED
#define SPI_H_INCLUDED
#define START_AC 7
#define CH2_AC 6
#define CH1_AC 5
#define CH0_AC 4
#define DIF_AC 3
#define R2_AC 2
#define R1_AC 1
#define R0_AC 0
#define M2_AC 6
#define M1_AC 5
#define M0_AC 4
void transmisja (void);
void spi_master_init(void);
void spi_send (unsigned char data);
void spi_ac_run (void);
char spi_read (void);
void write_ca_napiecie (unsigned int napiecie,unsigned int gain);
void write_ca_prad (unsigned int prad,unsigned int gain);
void write_ca_pomiar (unsigned int gain_prad,unsigned int gain_napiecie);
unsigned char conversion_byte;
unsigned char analog_byte;
unsigned char mode_byte;
volatile char marker1;
#endif
spi.c
#include <avr/io.h>
#include <string.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdlib.h>
#include "harddef.h"
#include "spi.h"
#include "uart.h"
#include "diody.h"
#include "lcd.h"
unsigned char conversion_byte=(1<<START_AC);
unsigned char analog_byte=(1<<START_AC)|(1<<R0_AC);
unsigned char mode_byte=(1<<START_AC)|(1<<M1_AC)|(1<<3);
extern char zmiana;
extern char z;
extern volatile unsigned char wynik_msb;
extern volatile unsigned char wynik_lsb;
void spi_master_init(void)
{
SPI_DDR = (_BV(MOSI)|_BV(SCK)|_BV(AC));
AC_OFF;
SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0); //konfiguracja rejestru SPCR
}
void spi_send (unsigned char data)
{
SPDR=data;
while(!(SPSR & (1<<SPIF)));
}
char spi_read (void)
{
while(!(SPSR & (1<<SPIF)));
return SPDR;
}
void spi_ac_run (void)
{
AC_ON;
spi_send(conversion_byte);
/*spi_send(0x00); //ten fragment kodu, objęty w w komentarz umozliwia przeprowadzenie
//konwersji w trybie zewnętrznym, przy jednoczesnym wyłączeniu przerwań
spi_send(0x00);
wynik_msb=spi_read();
spi_send(0x00);
wynik_lsb=spi_read();
*/
AC_OFF;
sei(); //włączenie przerwań
}
przerwania.h
#ifndef INTERRUPT_H_INCLUDED
#define INTERRUPT_H_INCLUDED
void ex_interrupt(void);
#endif
przerwania.c
#include <avr/io.h> // dostęp do rejestrów
#include <avr/interrupt.h>
#include <stdlib.h>
#include "spi.h"
#include "uart.h"
#include "diody.h"
void ex_interrupt(void)
{
MCUCR=(1<<ISC00); //tu daje albo MCUCR=(1<<ISC00); żeby wykrywał każda zmianę sygnały SSTRB,
//lub nie daję nic jeśli chcę wykrywanie na poziom niski na INT0
GICR = (1<<INT0);
}
main.c
#include <avr/io.h>
#include <avr/interrupt.h> //Zawiera funkcje obsługi przerwań.
#include <string.h>
#include <stdlib.h>
#include "uart.h"
#include "lcd.h"
#include "diody.h"
#include "key.h"
#include "spi.h"
#include "przerwania.h"
#include <util/delay.h>
#include "harddef.h"
//volatile uint8_t wynik_msb,wynik_lsb;
volatile unsigned int wynik=0;
volatile unsigned char wynik_msb=0;
volatile unsigned char wynik_lsb=0;
volatile double wynik_rzeczywisty;
volatile char bufor0[10];
char tablie[10];
char n=0,p=0;
char zmiana,zmiana_wartosci,zmiennik;
char z;
unsigned char bufor20[19];
unsigned char bufor10[5];
void impulsator (void)
{
cli();
if(bit_is_clear(PIND,impulsator_wy2))
ca_prad+=1;
else
ca_prad-=1;
_delay_ms(100);
lcd_goto(0,3);
utoa(ca_prad,bufor10,10);
lcd_write_table_text(bufor10);
zmiana_wartosci=1;
}
void transmisja (void)
{
cli();
AC_ON;
spi_send(0x00);
wynik_msb=spi_read();
spi_send(0x00);
wynik_lsb=spi_read();
AC_OFF;
zmiana_wartosci++;
utoa(zmiana_wartosci,bufor10,10);
lcd_goto(0,3);
lcd_write_table_text(bufor10);
zmiennik=1;
}
ISR(INT0_vect)
{
transmisja();
}
ISR(INT1_vect)
{
impulsator();
}
//////////////////////// **** program główny **** //////////////////////////////////
int main(void)
{
//DDRx= 0 -wejscie ; 1 -wyjscie
DDRD &=~ (_BV(impulsator_wy1)|_BV(impulsator_wy2)|_BV(AC_SSTRB));
PORTD |= _BV(impulsator_wy1)|_BV(impulsator_wy2)|_BV(AC_SSTRB);
lcd_init();
lcd_clear();
ex_interrupt();
spi_master_init();
_delay_us(1);
AC_ON;
spi_send(analog_byte);
AC_OFF;
_delay_us(1);
AC_ON;
spi_send(mode_byte);
AC_OFF;
spi_ac_run();
while(1)
{
wynik=wynik_msb;
wynik<<=8;
wynik|=wynik_lsb;
utoa(wynik,bufor20,10);
lcd_goto(0,0);
lcd_write_table_text(bufor20);
wynik_rzeczywisty=(wynik-32768)*0.000091;
dtostrf(wynik_rzeczywisty,3,6,bufor20);
lcd_goto(0,1);
lcd_write_table_text(bufor20);
lcd_write_data(0x20);
lcd_write_data(0x20);
for(char i=0;i<10;i++)
{
_delay_ms(100);
}
spi_ac_run();
}
}
