|
|
  |
stm32 uart rs485, описание прерывания на прием в буфер (и на передачу) |
|
|
|
Apr 20 2012, 15:57
|
Частый гость
 
Группа: Участник
Сообщений: 129
Регистрация: 6-11-05
Пользователь №: 10 508

|
ситуация такая, нужно написать прерывание на прием в буфер и в зависимости от значения первого байта в ответ отправить другой буфер (около 20 байт). ниже кусок прерывания для одного байта. как его переделать для буфера??? помогите!!! Код void USART1_IRQHandler(void) { //Receive Data register not empty interrupt if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) { rx=1; USART_ClearITPendingBit(USART1, USART_IT_RXNE); tmp=USART_ReceiveData (USART1);
} //Transmission complete interrupt if(USART_GetITStatus(USART1, USART_IT_TC) != RESET) { USART_ClearITPendingBit(USART1, USART_IT_TC); tx_end=1; }
|
|
|
|
|
Apr 21 2012, 10:11
|

Частый гость
 
Группа: Участник
Сообщений: 116
Регистрация: 27-01-10
Из: СПб
Пользователь №: 55 094

|
Не уверен, что верно понял, что Вам нужно. Но я использую два кольцевых буфера, на прием и передачу. CODE #define USART1_BUF_SIZE (64) #define USART1_BUF_MASK (USART1_BUF_SIZE - 1)
typedef struct { uint8_t buf [USART1_BUF_SIZE]; uint8_t in; uint8_t out; uint8_t count; } usart1_buf_t;
volatile static usart1_buf_t usart1_rx, usart1_tx;
extern void usart1_putchar (uint8_t symb) { if ((USART1->SR & USART_SR_TXE) && !usart1_tx.count) { USART1->DR = symb; } else if (usart1_tx.count < USART1_BUF_SIZE) { usart1_tx.buf [usart1_tx.in++] = symb; usart1_tx.count++; usart1_tx.in &= USART1_BUF_MASK; }; };
extern uint8_t usart1_getchar (void) { uint8_t symb; if (usart1_rx.count > 0) { symb = usart1_rx.buf [usart1_rx.out++]; usart1_rx.count--; usart1_rx.out &= USART1_BUF_MASK; return symb; }; return 0; };
void USART1_IRQHandler (void) { if (USART1->SR & USART_SR_TC) { USART1->SR &= ~USART_SR_TC; if (usart1_tx.count > 0) { USART1->DR = usart1_tx.buf [usart1_tx.out++]; usart1_tx.count--; usart1_tx.out &= USART1_BUF_MASK; }; } else if (USART1->SR & USART_SR_RXNE) { USART1->SR &= ~USART_SR_RXNE; if (usart1_rx.count < USART1_BUF_SIZE) { usart1_rx.buf [usart1_rx.in++] = USART1->DR; usart1_rx.in &= USART1_BUF_MASK; usart1_rx.count++; }; }; };
Сообщение отредактировал ohmjke - Apr 21 2012, 10:15
|
|
|
|
|
Apr 21 2012, 15:00
|
Частый гость
 
Группа: Участник
Сообщений: 129
Регистрация: 6-11-05
Пользователь №: 10 508

|
Цитата(ohmjke @ Apr 21 2012, 13:11)  Не уверен, что верно понял, что Вам нужно. Но я использую два кольцевых буфера, на прием и передачу. CODE #define USART1_BUF_SIZE (64) #define USART1_BUF_MASK (USART1_BUF_SIZE - 1)
typedef struct { uint8_t buf [USART1_BUF_SIZE]; uint8_t in; uint8_t out; uint8_t count; } usart1_buf_t;
volatile static usart1_buf_t usart1_rx, usart1_tx;
extern void usart1_putchar (uint8_t symb) { if ((USART1->SR & USART_SR_TXE) && !usart1_tx.count) { USART1->DR = symb; } else if (usart1_tx.count < USART1_BUF_SIZE) { usart1_tx.buf [usart1_tx.in++] = symb; usart1_tx.count++; usart1_tx.in &= USART1_BUF_MASK; }; };
extern uint8_t usart1_getchar (void) { uint8_t symb; if (usart1_rx.count > 0) { symb = usart1_rx.buf [usart1_rx.out++]; usart1_rx.count--; usart1_rx.out &= USART1_BUF_MASK; return symb; }; return 0; };
void USART1_IRQHandler (void) { if (USART1->SR & USART_SR_TC) { USART1->SR &= ~USART_SR_TC; if (usart1_tx.count > 0) { USART1->DR = usart1_tx.buf [usart1_tx.out++]; usart1_tx.count--; usart1_tx.out &= USART1_BUF_MASK; }; } else if (USART1->SR & USART_SR_RXNE) { USART1->SR &= ~USART_SR_RXNE; if (usart1_rx.count < USART1_BUF_SIZE) { usart1_rx.buf [usart1_rx.in++] = USART1->DR; usart1_rx.in &= USART1_BUF_MASK; usart1_rx.count++; }; }; }; не понятно когда вызывается прерывание на передачу буфера (ну или как запустить передачу буфера) и зачем нужны функции extern void usart1_putchar (uint8_t symb) и extern uint8_t usart1_getchar (void) . прием осуществляется по прерыванию, т.е. каждый байт по прерыванию, я думал что нужно один байт принять по прерыванию а остальные по проверке флага...
|
|
|
|
|
Apr 21 2012, 15:06
|

Частый гость
 
Группа: Участник
Сообщений: 116
Регистрация: 27-01-10
Из: СПб
Пользователь №: 55 094

|
Цитата(dimka2001 @ Apr 21 2012, 19:00)  ну или как запустить передачу буфера Вызывать в цикле функцию usart1_putchar(); Данные из Вашего буфера попадут в передающий кольцевой буфер, а затем уже передадутся по usart'y. Данные принимаются без всяких функций, они складываются в приемный буфер, для этого нужен лишь обработчик прерывания по завершению приема. А вот usart1_getchar (); - чтение байта из приемного кольцевого буфера.
|
|
|
|
|
Apr 21 2012, 16:11
|
Частый гость
 
Группа: Участник
Сообщений: 129
Регистрация: 6-11-05
Пользователь №: 10 508

|
Цитата(ohmjke @ Apr 21 2012, 18:06)  Вызывать в цикле функцию usart1_putchar(); Данные из Вашего буфера попадут в передающий кольцевой буфер, а затем уже передадутся по usart'y. Данные принимаются без всяких функций, они складываются в приемный буфер, для этого нужен лишь обработчик прерывания по завершению приема. А вот usart1_getchar (); - чтение байта из приемного кольцевого буфера. не понятно в функции usart1_putchar() байт записывается в uart и в прерывании if ((USART1->SR & USART_SR_TXE) && !usart1_tx.count) { USART1->DR = symb; и в прерывании USART1->DR = usart1_tx.buf [usart1_tx.out++]; и что такое кольцевой буфер???
|
|
|
|
|
Apr 21 2012, 16:33
|
Гуру
     
Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322

|
Цитата(dimka2001 @ Apr 21 2012, 19:11)  не понятно в функции usart1_putchar() байт записывается в uart и в прерывании Видимо, не в прерывании записывается первый байт посылки (при условии что буфер пуст и буфер USART также пустой). Остальные байты пишутся по прерыванию освобождения буфера USART. Цитата(dimka2001 @ Apr 21 2012, 19:11)  и что такое кольцевой буфер??? Кольцевой буфер - стандартный прием ортанизации приёма/передачи и тп Спросите гугла. Он знает.
|
|
|
|
|
Apr 21 2012, 16:39
|

Частый гость
 
Группа: Участник
Сообщений: 116
Регистрация: 27-01-10
Из: СПб
Пользователь №: 55 094

|
Цитата(dimka2001 @ Apr 21 2012, 20:11)  не понятно в функции usart1_putchar() байт записывается в uart if ((USART1->SR & USART_SR_TXE) && !usart1_tx.count) { USART1->DR = symb; Это происходит лишь в том случае, если закончена передача предыдущего байта и данных в кольцевом передающем буфере нет. Т.е., это сделано для того, чтобы не использовать буфер без надобности - нет лишних операций. Цитата(dimka2001 @ Apr 21 2012, 20:11)  и в прерывании USART1->DR = usart1_tx.buf [usart1_tx.out++]; Здесь же производится запись байта в регистр данных usart'a из буфера. Про кольцевой буфер можно почитать здесь - http://microsin.ru/content/view/1098/44/
|
|
|
|
|
Apr 21 2012, 19:28
|
Профессионал
    
Группа: Свой
Сообщений: 1 719
Регистрация: 13-09-05
Из: Novosibirsk
Пользователь №: 8 528

|
Цитата(ohmjke @ Apr 22 2012, 01:53)  И кстати, насчет модификации счетчиков - а что если применить bit-banding? а как? Через этот механизм можно только логические операции с битами производить, зато атомарно. Инкремент/декремент так не сделать. С другой стороны, зачем вообще нужны эти счётчики, если работать с индексами массивов получается ничуть не хуже.
--------------------
Russia est omnis divisa in partes octo.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|