|
ATtiny2313 прием по SPI 4 байт |
|
|
|
Sep 19 2009, 10:15
|
Участник

Группа: Участник
Сообщений: 34
Регистрация: 10-11-07
Пользователь №: 32 211

|
на ATtiny2313 Необходимо принять 4 байта обьединить по 2 PWM_S = первые 2 байта Serv_S= вторые 2 байта И вывести PWM на 1 ножку если первые 2 байта больше 127 или на 2 ножку если меньше. ширина PWM пропорциональна значеию |X-127|. Код If PWM_S >= 127 Then PWM1 = Math.Abs(TextBox1.Text - 127) PWM2 = Disable Else PWM2= Math.Abs(TextBox1.Text - 127) PWM1 = Disable End If //PWM1 и PWM2 соответственно ширина 1 и 2 PWM а вторые 2 байта нужны для выдачи на 3 ножку сигнала(управление сервоприводом) частота 50Гц ширина импульса от 0.9мкс до 2.1 пропорционально полученному значению п.с. можно ли это реализовать на ATtiny26
|
|
|
|
|
Sep 19 2009, 14:00
|
Частый гость
 
Группа: Свой
Сообщений: 142
Регистрация: 18-02-08
Из: Челябинск
Пользователь №: 35 141

|
Вопрос навстречу, а зачем принимать по два байта, если из описания следует, что значения переменных ( по крайней мере, PWM_S) явно укладываются в один байт? Реализовать можно на чем угодно, особенно при наличии одного таймера с двумя выходами PWM и второго универсального таймера. Первая часть даже проще, чем Вы написали: Код if ( PWM_S > 127) { PWM1 = PWM_S - 127; PWM2 = 0; } else { PWM1 = 0; PWM2 = 127 - PWM_S; ] Во второй части и вовсе достаточно установить таймер в режим одиночного импульса и запускать в соответствии с принятым значением Serv_S. Период следования можно задавать программной задержкой, поскольку точности от него не требуется никакой.
Причина редактирования: Ненужное цитирование.
|
|
|
|
|
Sep 21 2009, 07:28
|
Участник

Группа: Участник
Сообщений: 34
Регистрация: 10-11-07
Пользователь №: 32 211

|
Т.е. нужно принимать 2 слова. А мне необходимо принять 1 слово и его обработать.
|
|
|
|
|
Sep 22 2009, 03:41
|
Частый гость
 
Группа: Свой
Сообщений: 142
Регистрация: 18-02-08
Из: Челябинск
Пользователь №: 35 141

|
Цитата(WreWolf @ Sep 21 2009, 13:28)  Т.е. нужно принимать 2 слова. А мне необходимо принять 1 слово и его обработать. Цитата Необходимо принять 4 байта обьединить по 2 PWM_S = первые 2 байта Serv_S= вторые 2 байта Что из этого истина?
|
|
|
|
|
Sep 22 2009, 10:51
|
Участник

Группа: Участник
Сообщений: 34
Регистрация: 10-11-07
Пользователь №: 32 211

|
принять 4 байта например: 0xAC7F PWM_S = 0xAC Serv_S=0x7F
|
|
|
|
|
Sep 23 2009, 05:16
|
Участник

Группа: Участник
Сообщений: 34
Регистрация: 10-11-07
Пользователь №: 32 211

|
действительно ( но в принципе суть в том что бы так разделить входноо сообщение. *pwm=0xAC7F; *pwm_s=*(pwm+1);
можно ли так? и как взыть по 1 байту? тип даных byte? byte pwm=*pwm; byte pwm_s=*pwm_s;
|
|
|
|
|
Sep 23 2009, 14:30
|
Частый гость
 
Группа: Свой
Сообщений: 142
Регистрация: 18-02-08
Из: Челябинск
Пользователь №: 35 141

|
Цитата(WreWolf @ Sep 23 2009, 11:16)  суть в том что бы так разделить входноо сообщение. *pwm=0xAC7F; *pwm_s=*(pwm+1); Суть в том, что SPI регистр в ATtiny2313 (как впрочем и во множестве других микроконтроллеров) имеет длину 8 бит и делить ничего не нужно! Вы, кажется, пытаетесь эмулировать работу микроконтроллера программой на PC, а надо бы начать с изучения его архитектуры.
|
|
|
|
|
Sep 23 2009, 17:07
|
Участник

Группа: Участник
Сообщений: 34
Регистрация: 10-11-07
Пользователь №: 32 211

|
Ну не совсем так. Пишется программа которая через LPT порт сможеть передать джанные значения в тиньку. Т.е. вы имеете в виду просто получить 2 байта. как это реализовать программно? требуется ли задержка при передаче с компьютера(м\у) байтами?
возможно ли выполнить 2 команды которые выполнят прием данных(если прием выполнен в виде в отдельной функции)
|
|
|
|
|
Sep 24 2009, 03:18
|
Частый гость
 
Группа: Свой
Сообщений: 142
Регистрация: 18-02-08
Из: Челябинск
Пользователь №: 35 141

|
Цитата(WreWolf @ Sep 23 2009, 23:07)  Пишется программа которая через LPT порт сможеть передать джанные значения в тиньку. Вы умеете управлять линиями LPT? Приведите фрагмент кода для передачи одного байта.
|
|
|
|
|
Sep 24 2009, 10:17
|
Участник

Группа: Участник
Сообщений: 34
Регистрация: 10-11-07
Пользователь №: 32 211

|
Ну этим занимаю не я. Этим занимается другой человек. Я занимаюсь приемным устройством. логика такая клок в 0 ждем цикл по колву бит установил данные ждем клок в 1 ждем клок в 0 возврат цикла Возможно ли использование данного кода CODE #include <avr\io.h> #include <avr\io2313.h>
//Function void USIinit(void); ISR (USI_OVERFLOW_vect);
int main(void) { USInit(); unsigned char pwm=ISR(); unsigned char pwm_s=ISR(); }
/* F-я Инициализация UPI*/ void USIinit(void) { DDRB = (1<<USI_PIN_DO); PORTB |= (1<<USI_PIN_DI) | (1<<USI_PIN_SCK); USICR = (1<<USIOIE) | (1<<USIWM0) | (1<<USICS1); }
/*Прием 1байт данных UPI*/ ISR (USI_OVERFLOW_vect) { int usi_in_buf[8]; int gBuf_ind_in=0; USISR |= (1<<USIOIF);
usi_in_buf[gBuf_ind_in] = USIDR; gBuf_ind_in++; return usi_in_buf; }
И вот то что я нашел еще как переписать на си. SPI Slave Operation Example The following code demonstrates how to use the USI module as a SPI Slave: CODE init: ldi r16,(1<<USIWM0)|(1<<USICS1) out USICR,r16 ... SlaveSPITransfer: out USIDR,r16 ldi r16,(1<<USIOIF) out USISR,r16 SlaveSPITransfer_loop: sbis USISR,USIOIF rjmp SlaveSPITransfer_loop in r16,USIDR ret
Как переделать это под вывод шим на 2 пина порта D CODE #include "iom16.h"
unsigned char pwm = 1; unsigned char inc = 1; // inc = 0 - уменьшать, inc = 1 - увеличивать яркость
void timer2_init() { OCR2 = 1; //ШИМ почти выключена // Быстрая ШИМ, переключать OC2 (PD7), увеличение таймера каждые 64 такта TCCR2 |= (1 << WGM20) | ( 1 << WGM21) | (1 << COM21) | (1 << CS22); }
void timer1_init() { OCR1A = 43200; //Прерывание 32 раза в секунду TCCR1A = 0; // СТС режим, увеличение таймера каждые 8 тактов TCCR1B |= (1 << WGM12) | (1 << CS11); // Прерывание по совпадению А таймера1 TIMSK |= (1 << OCIE1A); SREG |= (1 << 7); //Разрешить прерывания }
void io_init() //Инициализация портов ввода-вывода { DDRD = (1 << PD7)|(1 << PD6); //додумался пока только до этого PORTD = 0; }
void main () { timer2_init(); timer1_init(); io_init(); while(1) { } }
// Заставляет лампу плавно загораться и гаснуть раз в 8 секунд #pragma vector = TIMER1_COMPA_vect __interrupt void PWM_change() { if (inc == 1) { if (pwm < 254) { pwm++; // Увеличиваем яркость лампы, пока не достигнем максимума OCR2 = pwm; } else { inc = 0; } } else { if (pwm > 1) { pwm--; // Уменьшаем яркость лампы, пока не остигнем минимума OCR2 = pwm; } else { inc = 1; } } }
|
|
|
|
|
Sep 25 2009, 11:17
|
Участник

Группа: Участник
Сообщений: 34
Регистрация: 10-11-07
Пользователь №: 32 211

|
1) Обрывки кода выкинуты 2) Даташит прочитан. 3) В прерываниях ясности нет.(но в принципе можно на отдельную ножку кинуть прерывание и использовать ее как CS) Вот то что было сгенерировано из CVAVR Wissard и чтения даташита CODE #include <avr/power.h> #include <avr/eeprom.h> #include <avr/io.h> #include <avr/interrupt.h> #include <util/delay.h>
#define SPI_MOSI PINB5 #define SPI_MISO PINB6 #define SPI_SCK PINB7 #define DDR_SPI DDRB
#define F_CPU 8000000UL // 8 MHz
void SPI_SlaveInit(void)
{ // Set MOSI, SCK and SS as output, all others input DDR_SPI |= (1<<SPI_MISO) ; // Enable USI for SPI, External Clk, SPI mode 0 USICR |= (1<<USIWM0) | (1<<USICS1); }
uint8_t SPI_SlaveReceive(void) { while(!(USISR & (1<<USIOIF))); return USIDR; }
void SPI_SlaveTransmit(uint8_t ByteOfData) { USIDR = ByteOfData; while(!(USISR & (1<<USIOIF))); }
void pwm_io_init() //Инициализация портов ввода-вывода PWM для DC мотора { DDRB |= (1 << PINB1)|(1 << PINB2)|(1 << PINB3)|(1 << PINB4); PORTB = 0; }
int main(void) { uint8_t ByteOfData1; uint8_t PWM; uint8_t PWM_S; SPI_SlaveInit() ; _delay_us(10) ; while (1) { ByteOfData1 = SPI_SlaveReceive(); //Здесть псать обработку полученных данных } }
Сообщение отредактировал WreWolf - Sep 25 2009, 11:21
|
|
|
|
|
Sep 25 2009, 16:59
|
Участник

Группа: Участник
Сообщений: 34
Регистрация: 10-11-07
Пользователь №: 32 211

|
Нет у меня всего 2 PWM 1 для управления мотором 2 для управления сервоприводом
Т.е. вы имеете в виду сделать прерывание по срабатыванию 1 PWM и програмно дергать 4 ножки вслед за сигналом PWM
у 2313 есть аппарытный 2-х канальный PWM
а как быть с сигналом управления сервоприводом? это PWM с частотой 50Гц
|
|
|
|
|
Sep 26 2009, 13:45
|
Гуру
     
Группа: Свой
Сообщений: 3 123
Регистрация: 7-04-07
Из: Химки
Пользователь №: 26 847

|
Цитата(WreWolf @ Sep 25 2009, 20:59)  Нет у меня всего 2 PWM 1 для управления мотором 2 для управления сервоприводом А это что было? Цитата И вывести PWM на 1 ножку если первые 2 байта больше 127 или на 2 ножку если меньше. PWM генераторы (за редким исключением) выводят свой PWM на какую то конкретную ножку (одну). Т.е., что бы сделать вывод PWM на 2 ножки понадобытся 2 канала PWM. Плюс 50ти герцовый для управления сервоприводом Цитата Т.е. вы имеете в виду сделать прерывание по срабатыванию 1 PWM и програмно дергать 4 ножки вслед за сигналом PWM Нет, я имею в виду чисто програмный PWM (по прерыванию от таймера) Цитата у 2313 есть аппарытный 2-х канальный PWM а как быть с сигналом управления сервоприводом? это PWM с частотой 50Гц Замечательно. Тогда 2 первых канала ложатся на 2 PWM 2313, а 50Hz PWM делается по таймеру (таймер то свободный есть?)
|
|
|
|
|
Sep 28 2009, 09:03
|
Участник

Группа: Участник
Сообщений: 34
Регистрация: 10-11-07
Пользователь №: 32 211

|
всего есть 2 таймера если
вот там можно делать? Т.е. я понимаю по срабатыванию будет передано управление на прерывание, где я смогу сделать то что нужно
|
|
|
|
|
Sep 30 2009, 08:08
|
Участник

Группа: Участник
Сообщений: 34
Регистрация: 10-11-07
Пользователь №: 32 211

|
CODE #include <avr/power.h> #include <avr/eeprom.h> #include <avr/io.h> #include <avr/interrupt.h> #include <util/delay.h>
#define SPI_MOSI PINB5 #define SPI_MISO PINB6 #define SPI_SCK PINB7 #define DDR_SPI DDRB
#define F_CPU 8000000UL // 8 MHz uint8_t PULSE_WIDTH=0x40; uint8_t SERVO=0x7F;
void SPI_SlaveInit(void) { // Set MOSI, SCK and SS as output, all others input DDR_SPI |= (1<<SPI_MISO) ; // Enable USI for SPI, External Clk, SPI mode 0 USICR |= (1<<USIWM0) | (1<<USICS1); } uint8_t SPI_SlaveReceive(void) { while(!(USISR & (1<<USIOIF))); return USIDR; }
void SPI_SlaveTransmit(uint8_t ByteOfData) { USIDR = ByteOfData; while(!(USISR & (1<<USIOIF))); }
void pwm_io_init() //Инициализация портов ввода-вывода PWM для DC мотора { DDRB |= (1 << PINB1)|(1 << PINB2)|(1 << PINB3)|(1 << PINB4); PORTB = 0; }
void pwm_start() { uint8_t V; if (PULSE_WIDTH>127) { V=(PULSE_WIDTH-127)/256; OCR1AL = V; //Load Pulse width OCR1AH = 0; TCCR1A = 0x81; //8-bit, Non-Inverted PWM TCCR1B = 1; //Start PWM }else{ V=(127-PULSE_WIDTH)/256; OCR1BL = V; //Load Pulse width OCR1BH = 0; TCCR0A = 0x81; //8-bit, Non-Inverted PWM TCCR0B = 1; //Start PWM } }
int main(void) { uint8_t ByteOfData1; SPI_SlaveInit() ; _delay_us(10) ; pwm_io_init(); _delay_us(10) ;
while (1) { ByteOfData1 = SPI_SlaveReceive(); PULSE_WIDTH = ByteOfData1; ByteOfData1 = SPI_SlaveReceive(); SERVO = ByteOfData1; pwm_start(); } }
Вот получилось вот так вывод ШИМ на 1 ил 2 ножку
|
|
|
|
|
Sep 30 2009, 09:30
|
Гуру
     
Группа: Свой
Сообщений: 3 123
Регистрация: 7-04-07
Из: Химки
Пользователь №: 26 847

|
Цитата(WreWolf @ Sep 28 2009, 13:03)  всего есть 2 таймера если
вот там можно делать? Если этот таймер не занят под PWM, то можно Цитата Т.е. я понимаю по срабатыванию будет передано управление на прерывание, где я смогу сделать то что нужно Да
|
|
|
|
|
Oct 13 2009, 07:57
|
Участник

Группа: Участник
Сообщений: 34
Регистрация: 10-11-07
Пользователь №: 32 211

|
Как в AVR Studio 4 написать обработчик прерываний?
|
|
|
|
|
Oct 13 2009, 16:06
|
Гуру
     
Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521

|
Цитата(WreWolf @ Oct 13 2009, 10:57)  Как в AVR Studio 4 написать обработчик прерываний? AVR Studio - это просто среда. Там можно набирать любую программу. В том числе и на Си. Поэтому вопрос некоректен. Думаю что вы хотели спросить "как написать обработчик прерывания на ассемблере". Если это так, то ответ следующий: 1) Обработчик прерывания - это обычная подпрограмма, переход на которую осуществляется по фиксированному вектору. Соответственно, вам надо написать подпрограмму, а в векторе-обработчика разместить переход на неё. 2) Надо учесть, что при переходе к обработке прерывания, автоматически сбрасывается бит разрешения прерывания. Соответственно необходимо разрешить его (если это требуется) при выходе. Обычно для этого используется инструкция reti вместо ret. 3) Надо почитать в даташите на данную микросхему необходимые дополнительные действия, если они есть. Так например иногда используется один общий обработчик для группы прерываний (флагов) или требуется ручной сброс флага прерывания и т.п. 4) Необходимо сохранить sreg а также используемые в прерывании регистры и восстановить их при выходе. Например так: Вектора: Код .cseg
rjmp init
;**************************************************************** ;* Прерывания. * ;****************************************************************
.if chip == 88 .org OC2Aaddr rjmp Tim2Cmp ; Обработка двигателя .org OVF0addr .else .org OC2addr rjmp Tim2Cmp ; Обработка двигателя .org OVF0addr .endif Обработчик: Код ;**************************************************************** ;* Прерывание от таймера 0. (180мkс) * ;****************************************************************
.equ PerIzm = 180 ; Период измерения 180 мкс .equ FuelCanal = 4-2 ; Канал измерения по частоте
Tim0Ovf: in tmpsreg,sreg ; Сохранить SREG ............ Tim0OvfEnd: out sreg, tmpsreg reti
|
|
|
|
|
Oct 17 2009, 09:19
|
Участник

Группа: Участник
Сообщений: 34
Регистрация: 10-11-07
Пользователь №: 32 211

|
Цитата 1) Обработчик прерывания - это обычная подпрограмма, переход на которую осуществляется по фиксированному вектору. Соответственно, вам надо написать подпрограмму, а в векторе-обработчика разместить переход на неё. Так понятнее. Цитата 2) Надо учесть, что при переходе к обработке прерывания, автоматически сбрасывается бит разрешения прерывания. Соответственно необходимо разрешить его (если это требуется) при выходе. Обычно для этого используется инструкция reti вместо ret. Цитата 3) Надо почитать в даташите на данную микросхему необходимые дополнительные действия, если они есть. Так например иногда используется один общий обработчик для группы прерываний (флагов) или требуется ручной сброс флага прерывания и т.п. Цитата 4) Необходимо сохранить sreg а также используемые в прерывании регистры и восстановить их при выходе. Зачем сохранять данные регистров. Если я не буду их трогать. Можно про реализацию на си
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|