How about something like this (untested):
SELECT COUNT(*) as myCount, TIMESTAMP( CONCAT( DATE(MIN(dateField)),' ',HOUR(MIN(dateField)),':00:00' ) ) as myTime FROM myTable GROUP BY CONCAT( DATE(dateField), HOUR(dateField) )
Should return the counts for each hour, and the hour for that count. This is better than running a query for each and every hour.
Edit: This would count every row in the DB, to get only rows between start and end just use a WHERE clause like you have already:
SELECT COUNT(*) as myCount, TIMESTAMP( CONCAT( DATE(MIN(dateField)),' ',HOUR(MIN(dateField)),':00:00' ) ) as myTime FROM myTable WHERE dateField BETWEEN '$startTime' AND '$endTime' GROUP BY CONCAT( DATE(dateField), HOUR(dateField) )
Just don't forget to make sure the start and end times are formatted properly!